// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
// perform the same computation on a set of elements

package main

import (
	"fmt"
	//	"time"
	//	"io/ioutil"
	//	"math/rand"
	"strconv"
	"strings"
	"bufio"
	"os"
	)

/* REQUEST *****************************************************/

// size for buffering requests
const BUF_SIZE = 100000

type Operator func (int) int

type Request struct {
	Op        Operator  // operator to be applied
	InputChan chan int  // chan to input elements to be processed 
	ReplyChan chan int  // chan where processed elements are returned
}

/* SERVER *****************************************************/

// parametrised by an input port for receiving
func server(service <-chan *Request) {
	for {
		req := <-service    // requests arrive here 
		go serve(req)       // don't wait for op
	}
}

// function serving the request: it inputs all elements from
// InputChan, create a process for each input, collect the results,
// send them to the ReplyChannel and close it
func serve(req *Request) {
	// create a channel for waiting slaves to complete
	done := make(chan bool, BUF_SIZE)
	numSlaves := 0
	for val := range req.InputChan {
		// concurrent or non-concurrent, this is the problem
		//slave(req.Op, val, req.ReplyChan, done)
		go slave(req.Op, val, req.ReplyChan, done)
		numSlaves++
	}
	for (numSlaves > 0) {
		<-done
		numSlaves--
	}
	close(req.ReplyChan)
}


// slave function for processing a single element
func slave(op Operator, val int, reply chan<- int, done chan<- bool) {
	reply <- op(val)
	done <- true
}
	

// function for starting the server: returns a port for sending requests
func startServer() chan<- *Request {
	service := make(chan *Request) 
	go server(service) 
	return service
}

// do some lengthy, but not CPU intensive work (IO bound)
func idWait (n int) int {	
	f, _ := os.Open("parallelize.go")
	defer f.Close()
	// Scan the file searching for occurrences of n	
	scanner := bufio.NewScanner(f)
	numstr := strconv.Itoa(n)
	// number of occurrences
	occurrences := 0
	for scanner.Scan() {
		if strings.Contains(scanner.Text(), numstr) {
			occurrences++
		}
	}
	return occurrences
	
}

// do some CPU intensive task
func useCPU (n int) int {
	sum := 0 
	for i:=0; i< n; i++ {
		for j:=0; j< n; j++ {
			sum = sum + i*j
		}
	}
	return sum
}

func main() {
	// create a server instance
	serverChan := startServer()
	
	// client side
	req := &Request{
		idWait,
		//useCPU,
		make(chan int, BUF_SIZE),
		make(chan int, BUF_SIZE)} 

	// elements to be processed [0, 1, 2, ..., Max]
	const Max = 10000
	

	// send the requests
	serverChan <- req

	for val := 0; val < Max; val++ {
		req.InputChan <- val
	}
	close(req.InputChan)
	
	// retrieve the results ranging on the return channel
	sum := 0
	for v := range req.ReplyChan {
		sum += v
	}

	fmt.Printf("Request out: %d\n", sum)
}
