Simplified concurrency mechanisms for goroutines

It does not longer make sense to have a mutex and cancelled context check
since we have a wait group and channels with buffers with the size equal
the number of workers.

Without the wait group we had to make sure no goroutine tries to write
to the closed channel. Now, channel is closed after all goroutines
completed (either by finding prime or cancelling the work), so there is
no chance someone tries to write to closed channel.
This commit is contained in:
Piotr Dyraga committed 2018-07-30 15:46:16 +02:00
1 parent b21e0d7d97
commit 82f050d7b2
1 file changed
+3 -16
+3 -16
View File
@@ -74,7 +74,6 @@ func GenerateSafePrime(
defer close(primeChan)
defer close(errChan)
mutex := &sync.Mutex{}
waitGroup := &sync.WaitGroup{}
ctx, cancel := context.WithCancel(context.Background())
@@ -82,28 +81,22 @@ func GenerateSafePrime(
for i := 0; i < concurrencyLevel; i++ {
waitGroup.Add(1)
runGenPrimeRoutine(
ctx, primeChan, errChan, mutex, waitGroup, random, bitLen,
ctx, primeChan, errChan, waitGroup, random, bitLen,
)
}
// Cancel after the specified timeout.
go func() {
time.Sleep(timeout)
mutex.Lock()
cancel()
mutex.Unlock()
}()
select {
case result := <-primeChan:
mutex.Lock()
cancel()
mutex.Unlock()
p, q, err = result.p, result.q, nil
case err := <-errChan:
mutex.Lock()
cancel()
mutex.Unlock()
p, q, err = nil, nil, err
case <-ctx.Done():
p, q, err = nil, nil, fmt.Errorf("generator timed out after %v", timeout)
@@ -157,7 +150,6 @@ func runGenPrimeRoutine(
ctx context.Context,
primeChan chan safePrime,
errChan chan error,
mutex *sync.Mutex,
waitGroup *sync.WaitGroup,
rand io.Reader,
pBitLen int,
@@ -175,10 +167,11 @@ func runGenPrimeRoutine(
bigMod := new(big.Int)
go func() {
defer waitGroup.Done()
for {
select {
case <-ctx.Done():
waitGroup.Done()
return
default:
_, err := io.ReadFull(rand, bytes)
@@ -266,13 +259,7 @@ func runGenPrimeRoutine(
isPocklingtonCriterionSatisfied(p) &&
q.BitLen() == qBitLen {
mutex.Lock()
if ctx.Err() == nil {
primeChan <- safePrime{p, q}
}
mutex.Unlock()
waitGroup.Done()
return
}
}