On Fri, Oct 04, 2013 at 04:52:40PM +0200, Luca wrote: > Il giorno 04 ottobre 2013 15:34, Marco Giusti <marco.giu...@gmail.com> ha > scritto: > > > > > Perdonami, puoi spiegarmelo come se avessi cinque anni? Sembra, da come > > lo descrivi, che la copia di un file debba essere interrotta a metà per > > poi riprendere con una politica differente. Invece il tuo codice sembra > > dire il contrario, ovvero una copia deve essere finita sempre con la > > politica con cui ha iniziato ma ogni nuova copia deve o aspettare una > > risposta o utilizzare la politica selezionata. > > > Beh a dire il vero è opinione comunque che io sia un genio ad esporre male > le cose :\ > > in effetti è come dici tu. è la nuova copia che parte che deve aspettre > una risposta. > Solo che la verifica vene fatta dentro al worker. > > Ti pastobinno la funzione operaia con le modifiche che stavo cercando di > testare sullo script di test. > Magari così capisci meglio che intendo e magari mi indicate altri errori di > concetto. > > http://pastebin.com/rFLzW7xy
Senza (troppo) leggere il tuo codice, concettualmente allora è come avevo descritto nella mia prima email. Supponi che hai i due lock come ti avevo descritto, il worker si comporta più o meno così: def worker(): while True: path = q.get() if os.path.exists(path) and override is ASK: with w: global override override = ask_dialog() with r: copy(path) q.task_done() questo è a larghe spanne quello che dovrebbe fare. I due lock sono speciali. r lo puoi acquisire solo se nessuno reclama w. w lo puoi acquisire solo se nessuno ha acquisito r. Così se due operazioni di copia sono in atto e una terza vuole sovrascrivere un file, la terza si blocca fintanto che le due precedenti non sono completate. Nuove operazioni di copia sono bloccate perché qualcuno reclama w. Quando w viene rilasciato, i worker possono di nuovo acquisire r. Ti allego un esempio con il lock preso qui[1]. Ciao Marco [1] http://code.activestate.com/recipes/577803-reader-writer-lock-with-priority-for-writers/
import os import time import threading import Queue class _LightSwitch: def __init__(self, lock): self.__counter = 0 self.__mutex = threading.Lock() self.__lock = lock def acquire(self): self.__mutex.acquire() self.__counter += 1 if self.__counter == 1: self.__lock.acquire() self.__mutex.release() def release(self): self.__mutex.acquire() self.__counter -= 1 if self.__counter == 0: self.__lock.release() self.__mutex.release() def __enter__(self): return self.acquire() def __exit__(self, exc_value, exc_type, traceback): self.release() def RWLock(): no_readers = threading.Lock() no_writers = threading.Lock() readers_queue = threading.Lock() read_switch = _LightSwitch(no_writers) write_switch = _LightSwitch(no_readers) class ReadLock: def acquire(self): readers_queue.acquire() no_readers.acquire() read_switch.acquire() no_readers.release() readers_queue.release() def release(self): read_switch.release() def __enter__(self): return self.acquire() def __exit__(self, exc_value, exc_type, traceback): self.release() class WriteLock: def acquire(self): write_switch.acquire() no_writers.acquire() def release(self): no_writers.release() write_switch.release() def __enter__(self): return self.acquire() def __exit__(self, exc_value, exc_type, traceback): self.release() return ReadLock(), WriteLock() class Thread(threading.Thread): def __init__(self, target, *args): threading.Thread.__init__(self, target=target, args=args) self.daemon = True self.start() ASK = object() ALWAYS = object() NEVER = object() override = ASK def ask_dialog(path): ask = None while ask not in ("yes", "no", "never", "always"): print "Should I override %s?" % path ask = raw_input("type 'yes', 'no', 'never' or 'always': ") return ask def copy(path, t): print "copying", path time.sleep(t) print "finished copying", path def worker(q, r, w, t): global override while True: path = q.get() if os.path.exists(path): with w: if override is ALWAYS: pass elif override is NEVER: q.task_done() continue elif override is ASK: o = ask_dialog(path) if o in ("no", "never"): if o == "never": override = NEVER q.task_done() continue elif o == "always": override = ALWAYS with r: copy(path, t) q.task_done() if __name__ == "__main__": r, w = RWLock() q = Queue.Queue() paths = ("/tmp/cucu", "/tmp/cucucu", "/etc/passwd", "/etc/group") for path in paths: q.put(path) [Thread(worker, q, r, w, t) for t in (1, 2, 1, 1)] q.join()
_______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python