2012-07-01 13 views
10

Speravo di utilizzare System.INotify e System.IO.MMap insieme per controllare le modifiche ai file e quindi eseguire rapidamente diff per l'invio di patch su una rete. Tuttavia, nella documentazione per System.IO.MMap ci sono un paio di avvertimenti circa trasparenza referenziale:Trasparenza referenziale e mmap in Haskell

La documentazione

E 'sicuro solo per mmap un file se sai che sei l'unico utente. Altrimenti la trasparenza referenziale potrebbe essere o non essere compromessa. Purtroppo la semantica differisce molto tra i sistemi operativi.

I valori che i rendimenti sono mmap IO ByteString, sicuramente quando uso questo valore con putStr mi aspetto un risultato diverso ogni volta? Suppongo che l'autore significhi che il valore potrebbe cambiare durante un'operazione IO come putStr e crash?

di inizio EDIT: Vieni a pensarci bene, credo risposta a questa parte della domanda è alquanto ovvia ... Se il valore cambia in qualsiasi momento dopo è unboxed sarebbe problematico.

do 
    v <- mappedValue :: IO ByteString 
    putStr v 
    putStr v -- Expects the same value of v everywhere 

FINE EDIT

non dovrebbe essere possibile acquisire un qualche tipo di blocco sulla regione mappata o sul file?

In alternativa, sarebbe possibile scrivere una funzione copy :: IO ByteString -> IO ByteString che acquisisca un'istantanea del file nel suo stato corrente in modo sicuro?

+0

Mi sembra che quello che vuoi possa essere fatto anche con un semplice paio di tubi. – leftaroundabout

+0

Sto "guardando" i file in una directory in un modo un po 'generico. Se qualche strumento li tocca, i client vengono aggiornati automaticamente. –

+1

Non c'è davvero nessuna libreria mmap che offra qualcosa di tipo 'IO (Ptr Word8)' o simile? –

risposta

8

Penso che l'autore significhi che il valore può cambiare anche all'interno di una funzione sollevata che può visualizzarlo come un semplice ByteString (senza IO).

Il file mappato meory è un'area di memoria. Non ha molto senso copiare il suo contenuto avanti e indietro, per motivi di prestazioni (altrimenti si potrebbe semplicemente fare un semplice I/O basato sul flusso vecchio). Quindi il ByteString che stai ricevendo è live.

Se si desidera avere un'istantanea, è sufficiente utilizzare un I/O basato sul flusso. Questo è ciò che legge un file: crea un'istantanea di file nella memoria! Suppongo che un'alternativa utilizzi l'interfaccia ForeignPtr che non contiene l'avviso di trasparenza referenziale. Non ho familiarità con ForeignPtrs quindi non posso garantire che funzionerà, ma sembra promettente e vorrei indagare.

Puoi anche provare a chiamare map id sul tuo ByteString ma non è garantito che otterrai una copia distinta dall'originale.

Il blocco di file obbligatorio, soprattutto su Linux, è un pasticcio che è meglio evitare. Il blocco del file consultivo è OK, tranne che nessuno lo sta utilizzando, quindi in realtà non esiste.

+2

Immagino che inconsciamente io ' Mi aspetto un po 'troppo dal mio sistema operativo. Volevo trattare il file, fondamentalmente, come una cache di memoria condivisa molto veloce tra più processi, lasciando che il sistema operativo si occupasse di eseguire il flushing delle modifiche su disco a volontà. Pensandoci più attentamente immagino che sembra piuttosto improbabile che funzioni a meno che tutti i processi non utilizzino esplicitamente una mappa di memoria condivisa. –

+0

(Vedi, speravo di evitare di incorrere nella latenza coinvolta nel toccare il disco fisico ...) –