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

Rispondere a