Domanda

Se faccio

Process.fork do 
  x 
end 

come posso sapere che cosa X restituito (ad esempio true / fase / string)?

(scrittura di un file / database non è un'opzione ...)

È stato utile?

Soluzione 3

ho avvolto tutte le soluzioni ho trovato lungo la strada (alcuni altri problemi come l'uscita dell'utente + tubazioni-buffer) in rubino parallelamente gemma. Ora è facile come:

results = Parallel.map([1,2,3],:in_processes=>4) do |i|
  execute_something(i)
end

o

results = Parallel.map([1,2,3],:in_threads=>4) do |i|
  execute_something(i)
end

Altri suggerimenti

In realtà abbiamo avuto solo per gestire questo problema in Rails isolamento test . Ho pubblicato su di esso un po ' sul mio blog .

In sostanza, ciò che si vuole fare è aprire un tubo nel genitore e figlio, e avere il bambino scrivere al tubo. Ecco un modo semplice per eseguire il contenuto di un blocco in un processo figlio e tornare il risultato:

def do_in_child
  read, write = IO.pipe

  pid = fork do
    read.close
    result = yield
    Marshal.dump(result, write)
    exit!(0) # skips exit handlers.
  end

  write.close
  result = read.read
  Process.wait(pid)
  raise "child failed" if result.empty?
  Marshal.load(result)
end

Poi si potrebbe eseguire:

do_in_child do
  require "some_polluting_library"
  SomePollutingLibrary.some_operation
end

Si noti che se si fa un richiedono nel bambino, non si avrà accesso a tale libreria nel genitore, quindi non è possibile restituire un oggetto di quel tipo con questo metodo. Tuttavia, si potrebbe restituire qualsiasi tipo che è disponibile sia.

Si noti inoltre che molti dei dettagli qui (read.close, Process.wait2(pid)) sono per lo più i dettagli di pulizia, quindi se si utilizza questo molto probabilmente si dovrebbe spostare questo fuori in una libreria di utilità che è possibile riutilizzare.

Infine, ricordiamo che questo non funzionerà su Windows o JRuby, dal momento che non supportano fork.

Grazie per tutte le risposte, ho ottenuto la mia soluzione attivo e funzionante, hanno ancora bisogno di vedere come gestire ambienti non si biforcano, ma per ora funziona:)

read, write = IO.pipe
Process.fork do
  write.puts "test"
end
Process.fork do
  write.puts 'test 2'
end

Process.wait
Process.wait

write.close
puts read.read
read.close

è possibile vederlo in azione @ parallel_specs Rails plug

Sì, è possibile creare un sottoprocesso per eseguire un blocco all'interno.

il aw gemma :

Aw.fork! { 6 * 7 } # => 42

Naturalmente, impedisce di effetti collaterali:

arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]

Secondo la documentazione:

  

Se viene specificato un blocco, tale blocco viene eseguito nel sottoprocesso, e il sottoprocesso termina con uno stato di zero.

Quindi, se lo si chiama con un blocco, restituisce 0. In caso contrario, funziona fondamentalmente lo stesso come la chiamata di sistema fork() su Unix (il genitore riceve il PID del nuovo processo, il bambino riceve nil) .

La comunicazione tra due processi forcella Unix è principalmente il codice di ritorno e nulla più. Tuttavia, si potrebbe aprire un filedescriptor tra i due processi e passaggio dei dati tra i processi più di questo filedescriptor:. Questo è il modo normale tubo di Unix

Se volete passare Marshal.dump () e Marshal.load () i valori, si potrebbe facilmente passare oggetti di Ruby tra quei processi Ruby.

È possibile utilizzare la memoria condivisa per fare questo se il bambino ha solo bisogno di essere un piccolo pezzo di codice Ruby. Qualcosa di simile a quanto segue funzionerà:

str = 'from parent'

Thread.new do
  str = 'from child'
end

sleep(1)

puts str    # outputs "from child"

La concorrenza può essere piuttosto difficile, però, e l'accesso a memoria condivisa in questo modo è una grande parte della ragione - ogni volta che hai una variabile e un altro processo potrebbe cambiare da sotto, si dovrebbe essere molto cauti. In alternativa, è possibile utilizzare un tubo, che è più ingombrante, ma probabilmente più sicuro per qualsiasi ma il codice più banale, e può anche essere utilizzato per eseguire qualsiasi comando arbitrario. Ecco un esempio, non appena estratto dalla rdoc per IO.popen:

f = IO.popen("uname")
p f.readlines     # outputs "Darwin", at least on my box  :-)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top