pvtest.php 2.45 KB
<?php

/*
 * Zunächst mal den Gedanken skizziert
 * Da es kein wirklich zuverlässiges Locking fuer kritische Bereiche
 * in php gibt. Semaphore existiren nur unter Unix und flock arbeitet nicht
 * wenn der webserver threaded ist und keine separaten prozesse pro
 * request erzeugt habe ich folgenden Gedankengang...nicht 100% Atomar, aber
 * möglicherweise das beste was man bekommen kann.
 *
 *  ACQUIRE
 *  =======
 *     |
 *   - leere Datei erzeugen (tmp)
 *   - link (tmp) nach (lock)
 *     |
 *     |-----------------------------
 *  OK |             |       Fehler |
 *     |             |              |
 *     |             |  - lese (lock): sollte blockieren solange diese leer ist
 *     |             |  - unlink (lock)
 *     |             |  - link (tmp) nach (lock)
 *     |      Fehler |              |
 *     |             ---------------|
 *     |                            | OK
 *     |                            |
 *     |-----------------------------
 *     |
 *   - (tmp) loeschen
 *     |
 *   (ENDE)
 *
 * RELEASE
 * =======
 *     |
 *   - schreibe nach (lock)
 *     |
 *   (ENDE)
 *
 * Da link angeblick atomar ist muesste das zumindest zuverlaessig Sperren...
 * Zusaettzlich sollte man vielleicht noch ein Priorisierung irgendwo 
 * festhalten, um zu verhindern das ein Prozess ewig wartet, weil er immer
 * Pech bei der zuweisung von CPU Zeit hat.
 *
 * So ein Pech, read blockiert natuerlich nicht bei regulären Dateien, da
 * ja EOF erreich wird....da muss ich mir was anderes ausdenken....
 * OK, unter UNIX kann ich exec mkfifo machen um eine named pipe zu generieren.
 * Fuer windows muss was anderes oder busy waiting (iiieeh) rein....
 *
 * !!! Zur info, schon der read open auf eine FIFO blocked wenn kein Writer
 * existiert. Das war auch ein aspekt den man berücksichtigen muß... !!!
 */

function acquire ($lock, $tmp)
{
	if (! file_exists ($tmp))
		exec ('mkfifo ' . $tmp);
	// hier koennte irgendwas bzgl. der Priorisierung in nem else folgen...

	if (link ($tmp, $lock) === FALSE)
	{
		while (true)
		{
			$handle = fopen ($lock, 'w');
			fwrite ($handel, '1');
			fclose ($handle);
			if (unlink ($lock) === FALSE) continue;
			if (link ($tmp, $lock) === FALSE) continue;
			break;
		}
	}

	unlink ($tmp);
}

function release ($lock)
{
	$handle = fopen ($lock, 'r');
	stream_set_blocking ($handle, 0);
	if (fread ($handle, 1) === 0)
		unlink ($lock);
	fclose ($handle);
}


acquire ('lock', 'tmp');

echo "Lock bekommen\n";
sleep (30);

release ('lock');

?>