code: func ExecuteInParallel(q *Queue, fn func(interface{})) {
  	if q == nil {
  		return
  	}
  
  	q.lock.Lock() // so no one touches anything in the middle
  	// of this process
  	todo, done := uint64(len(q.items)), int64(-1)
  	// this is important or we might face an infinite loop
  	if todo == 0 {
  		return
  	}
  
  	numCPU := 1
  	if runtime.NumCPU() > 1 {
  		numCPU = runtime.NumCPU() - 1
  	}
  
  	var wg sync.WaitGroup
  	wg.Add(numCPU)
  	items := q.items
  
  	for i := 0; i < numCPU; i++ {
  		go func() {
  			for {
  				index := atomic.AddInt64(&done, 1)
  				if index >= int64(todo) {
  					wg.Done()
  					break
  				}
  
  				fn(items[index])
  				items[index] = 0
  			}
  		}()
  	}
  	wg.Wait()
  	q.lock.Unlock()
  	q.Dispose()
  }
docs: // ExecuteInParallel will (in parallel) call the provided function
  // with each item in the queue until the queue is exhausted.  When the queue
  // is exhausted execution is complete and all goroutines will be killed.
  // This means that the queue will be disposed so cannot be used again.