2012-02-12 10 views
7

Estoy en OCaml.OCaml tutorial de evento/canal?

Busco para simular la comunicación de los nodos para ver cómo rápidamente mensajes se propagan bajo diferentes esquemas de comunicación, etc.

Los nodos pueden enviar 1. y 2. Recibir un mensaje fijo. Supongo que lo más obvio es tener cada nodo como un hilo separado.

Aparentemente, puede obtener subprocesos para pasar mensajes entre sí utilizando el módulo de evento y los canales, pero no puedo encontrar ningún ejemplo de esto. ¿Puede alguien señalarme en la dirección correcta o simplemente darme un ejemplo relevante simple?

Muchas gracias.

Respuesta

6

Si va a intentar una simulación, necesitará mucho más control sobre sus nodos que simplemente usar hilos permitirá — o al menos, sin mayores inconvenientes.

Mi enfoque subjetivo sobre el tema sería crear una máquina virtual simple de un solo hilo para mantener el control total de la simulación. La forma más fácil de hacerlo en OCaml es utilizar una estructura mónada similar (como se hace en peso liviano, por ejemplo):

(* 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 

Puede crear mejores primitivas que se adapten a sus necesidades, tales como la adición de un "tiempo requerido para transmitir "propiedad en sus canales.

El siguiente paso es definir un motor de simulación.

(* 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 

Una vez más, es posible ajustar el motor para realizar un seguimiento de lo que el nodo está ejecutando por cuál de ellos, para mantener las prioridades por nodo con el fin de simular un nodo de ser masivamente más lento o más rápido que otros, o escoger al azar un hilo para la ejecución en cada paso, y así sucesivamente.

El último paso es ejecutar una simulación. Aquí, voy a tener dos hilos que envían números aleatorios de un lado a otro.

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

Esa es una respuesta increíble, muy inspiradora. – Tiemen

5

Parece que estás pensando en John Reppy's Concurrent ML. Parece haber algo similar para OCaml here.

La respuesta que @Thomas ha dado también es valiosa, pero si desea utilizar este estilo de programación concurrente, le recomendaría leer PhD thesis de John Reppy que es extremadamente legible y da un tratamiento muy claro de la motivación detrás de CML y algunos ejemplos de su uso. Si no está interesado en la semántica, el documento aún puede leerse si omite esa parte.