Come suggerito da darbula ti serve uno stato condiviso in cui tenere traccia del timestamp dell'ultima azione eseguita. Però hai anche bisogno di un meccanismo di lock, il semplice accesso e controllo sui file non basta.
A dirla tutta, generalmente la concorrenza non va gestita basandosi sui tempi di esecuzione che sono inaffidabili e possono cambiare. Sono pochi i casi in cui ciò è indispensabile, il tuo potrebbe essere uno di questi, ma dovresti rifletterci bene.
Ad esempio, se io volessi usare un servizio del tuo sito ma mi venisse mostrato il messaggio "non puoi procedere perché qualcun'altro ha usato il servizio prima di te, aspetta 20 secondi e spera che nessuno ti freghi il posto", non sarei molto contento !
Piuttosto preferirei essere messo automaticamente in coda ed aspettare che il sistema elabori la mia richiesta.
Comunque, se intendi procedere, in pseudocodice suggerirei qualcosa del genere:
Codice:
cerca di acquisire il lock esclusivo sullo stato condiviso (termina in caso di fallimento)
acquisiscilo
leggi l'istante dell'ultima operazione dallo stato condiviso
se è trascorso almeno un determinato lasso di tempo dall'istante dell'ultima operazione procedi, altrimenti termina con fallimento
memorizza nello stato condiviso l'istante corrente
rilascia il lock
esegui il codice in questione
Che in codice si traduce, ad esempio, con qualcosa del genere:
Codice PHP:
// Cerca di acquisire il lock sullo stato condiviso e verifica il vincolo temporale.
// Restituisce il numero di secondi da attendere prima di poter procedere (0 se è possibile agire subito)
function get_lock($name = 'lock', $waiting_time = 5) {
$fp = is_readable($name) ? fopen($name, 'w') : fopen($name, 'r+');
if (!$fp) {
die("Errore durante l'accesso al file system.");
}
if (!flock($fp, LOCK_EX | LOCK_NB)) {
return $waiting_time;
}
$last_action_timestamp = fread($fp, filesize($name));
if (time() - $last_action_timestamp < $waiting_time) {
return $waiting_time - (time() - $last_action_timestamp);
}
truncate($fp, 0);
fwrite($fp, time());
fflush($fp);
flock($fp, LOCK_UN);
return 0;
}
$seconds_to_wait = get_lock('lock', 5);
if ($seconds_to_wait > 0) {
die("Non puoi procedere perché qualcun'altro ha usato il servizio prima di te, aspetta $seconds_to_wait secondi e spera che nessuno ti freghi il posto");
}
// Esegui il tuo codice
// ...