2012-02-12 16 views
7

Sono in OCaml.Esercitazione evento/canale OCaml?

Sto cercando di simulare comunicare i nodi da guardare quanto velocemente i messaggi si propagano nell'ambito di diversi regimi di comunicazione ecc

I nodi possono 1. invio e 2. riceverà un messaggio fisso. Immagino che la cosa ovvia da fare sia avere ciascun nodo come thread separato.

Apparentemente è possibile ottenere thread per passare messaggi tra loro utilizzando il modulo eventi ei canali, ma non riesco a trovare alcun esempio di questo. Qualcuno può indicarmi la giusta direzione o semplicemente darmi un semplice esempio pertinente?

Grazie mille.

risposta

6

Se si sta tentando una simulazione, sarà necessario un maggiore controllo sui nodi rispetto al semplice utilizzo dei thread consentirà di eseguire — o almeno senza problemi.

Il mio approccio soggettivo all'argomento sarebbe quello di creare una macchina virtuale semplice a thread singolo per mantenere il pieno controllo della simulazione. Il modo più semplice per farlo in OCaml è quello di utilizzare una struttura monade-simile (come avviene in LWT, per esempio):

(* A thread is a piece of code that can be executed to perform some 
    side-effects and fork zero, one or more threads before returning. 
    Some threads may block when waiting for an event to happen. *) 
type thread = < run : thread list ; block : bool > 

(* References can be used as communication channels out-of-the box (simply 
    read and write values ot them). To implement a blocking communication 
    pattern, use these two primitives: *) 

let write r x next = object (self) 
    method block = !r <> None 
    method run = if self # block then [self] 
       else r := Some x ; [next()] 
end 

let read r next = object (self) 
    method block = !r = None 
    method run = match r with 
        | None -> [self] 
        | Some x -> r := None ; [next x] 
end 

È possibile creare primitive meglio adatto alle vostre esigenze, come ad esempio l'aggiunta di un "tempo necessario per trasmettere "proprietà nei tuoi canali.

Il passaggio successivo è la definizione di un motore di simulazione.

(* The simulation engine can be implemented as a simple queue. It starts 
    with a pre-defined set of threads and returns when no threads are left, 
    or when all threads are blocking. *) 
let simulate threads = 
    let q = Queue.create() in 
    let() = List.iter (fun t -> Queue.push t q) threads in 
    let rec loop blocking = 
    if Queue.is_empty q then `AllThreadsTerminated else 
     if Queue.length q = blocking then `AllThreadsBlocked else 
     let thread = Queue.pop q in 
     if thread # block then ( 
      Queue.push thread q ; 
      loop (blocking + 1) 
     ) else ( 
      List.iter (fun t -> Queue.push t q) (thread # run) ; 
      loop 0 
     ) 
    in 
    loop 0 

Nuovamente, si può regolare il motore per tenere traccia di quale nodo sta eseguendo quale thread, per mantenere le priorità per-nodo in modo da simulare un nodo essendo massicciamente lento o più veloce rispetto ad altri, o raccogliendo casualmente un filo per l'esecuzione su ogni passaggio e così via.

L'ultimo passaggio è l'esecuzione di una simulazione. Qui, avrò due thread che inviano numeri casuali avanti e indietro.

let rec thread name input output = 
    write output (Random.int 1024) (fun() -> 
    read input (fun value -> 
     Printf.printf "%s : %d" name value ; 
     print_newline() ; 
     thread name input output 
)) 

let a = ref None and b = ref None 
let _ = simulate [ thread "A -> B" a b ; thread "B -> A" b a ]   
+0

Questa è una risposta fantastica, molto stimolante. – Tiemen

5

Sembra che stiate pensando a Concurrent ML di John Reppy. Sembra che ci sia qualcosa di simile per OCaml here.

La risposta @Thomas ha dato è anche utile, ma se si desidera utilizzare questo stile di programmazione concorrente Mi raccomando di leggere di PhD thesis John Reppy che è estremamente leggibile e dà una chiara trattamento della motivazione dietro CML e alcuni sostanziali esempi del suo uso. Se non sei interessato alla semantica, il documento è ancora leggibile se salti quella parte.

8

Sì, è possibile utilizzare il modulo Event di OCaml. È possibile trovare un esempio del suo utilizzo in linea O'Reilly book.