On Fri, Oct 04, 2013 at 04:52:40PM +0200, Luca wrote:
> Il giorno 04 ottobre 2013 15:34, Marco Giusti <[email protected]> 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
[email protected]
http://lists.python.it/mailman/listinfo/python