Skip to content

Instantly share code, notes, and snippets.

@Bebbolus
Created May 26, 2017 21:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bebbolus/6cdbc60bf50661172c1742f92502777a to your computer and use it in GitHub Desktop.
Save Bebbolus/6cdbc60bf50661172c1742f92502777a to your computer and use it in GitHub Desktop.
async PHP with generators
<?php
function isPrime($numberToCheck) {
for($i=0, $n=$numberToCheck-1; $n>1; $n--, $i++) {
yield $i;
if (!($numberToCheck % $n)) {
return false;
}
}
return true;
}
function checkPrime(Array $numbers) {
$tasks = $results = [];
foreach($numbers as $task => $number) {
$tasks[] = isPrime($number);
echo "Task $task instantiated\n";
}
$n = 0;
$j = count($tasks);
do {
$task = array_slice($tasks, $n % $j, 1);
$task = reset($task);
$current = $task->current();
if ($current === null) {
$results[$n % $j] = $task->getReturn();
$t = $n % $j;
yield ($n % $j) => [$current, $results[$n % $j]];
unset($tasks[$n % $j]);
$n++;
$j--;
if (!$j) {
break;
}
continue;
}
yield ($n % $j) => [$current, null];
$n++;
$task->next();
} while($tasks);
return $results;
}
foreach(checkPrime([7,4]) as $task => list($instruction, $result)) {
if ($result !== null) {
echo "Task $task completed with result " . ($result ? 'true' : 'false'), "\n";
} else {
echo "Executed instruction $instruction for task $task\n";
}
}
@Bebbolus
Copy link
Author

Dettaglio della funzione asincrona

Il nostro primo generatore sarà la funzione che controlla la primalità, che restituirà al suo termine se il numero è primo o meno ma, durante l'esecuzione, interromperà la sua esecuzione fornendo l'attuale posizione del contatore.

Creeremo quindi una seconda funzione che genera un array di task da eseguire (questa cosa può essere gestita meglio con un sistema di code ma per l'attuale esempio è esaustiva), e stampa un messaggio relativo a questa operazione per ogni numero da analizzare.
Itereremo tramite la funzione modulo all'interno del nostro array dei task, dichiarando quindi un contatore incrementale dei passi eseguiti e la variabile contenente il numero totale di task da eseguire.
Il ciclo do-while verrà eseguito finché saranno presenti task nel nostro array: prende (senza rimuoverlo) il task da eseguire, lo resetta per essere sicuro di partire dal primo elemento del generatore e ne legge la posizione corrente, se la posizione è nulla, significa che è finito il task e possiamo leggere il risultato finale (cioé se il valore in input è primo o no) e restituendo un array con chiave l'attuale task eseguito e come valore una lista (che in php è sempre un array) contenete null (il valore dell'attuale puntatore nel generatore isPrime) e il risultato ottenuto.
A questo punto eliminiamo il task dall'array visto che è finito e passiamo ad incrementare il contatore degli step eseguiti e decrementiamo quello dei tasks, se sono finiti i task, terminiamo l'esecuzione altrimenti continuiamo.
Nel caso non fosse terminato il nostro task invece restituiamo un array con chiave l'attuale task eseguito e come valore una lista contenete lo step interno eseguito nel nel generatore isPrime e null come il risultato ottenuto. Incrementiamo quindi il contatore degli step eseguiti e diciamo al nostro task di eseguire la successiva operazione.
Al termine di tutti i task ritorneremo l'array dei risultati precedentemente popolato.

Il nostro "main" consta di un ciclo foreach che itera per ogni task che verrà prodotto dal generatore checkPrime() assegnando le variabili dell'attuale istruzione eseguita e del risultato ottenuto.

All'interno del ciclo se il risultato ottenuto è nullo significa che l'attuale step non è terminato e restituiremo un messaggio relativo, altrimenti abbiamo il risultato di primalità e possiamo stamparlo a video.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment