-1

What I'd like to achieve is as follows (pseudocode):

f, t = select(files, threads)
if f
    <read from files>
elsif t
    <do something else>
end

Where select is a method similar to IO.select. But it seems unlikely to be possible.

The big picture is I'm trying to write a program which has to perform several types of jobs. The idea was to pass job data using database. But also inform the program about new jobs using pipes (by sending just type of the job). So that it wouldn't need to poll for jobs. So I was planning to create a loop waiting for either new notifications from pipes, or for worker threads to finish. After thread finishes I check if there were at least one notification about this particular type of job and run the worker thread again if needed. I'm not really sure what's is the best route to take here, so if you've got suggestions I'd like to hear them out.

x-yuri
  • 16,722
  • 15
  • 114
  • 161
  • what is `select`, and what is `files`, `threads`? Ruby does not have `elseif`. – sawa Jan 06 '14 at 19:11
  • You might find [this discussion](http://stackoverflow.com/questions/6241384/how-do-i-manage-ruby-threads-so-they-finish-all-their-work) helpful. – Cary Swoveland Jan 06 '14 at 19:28
  • @Cary Swoveland The interesting point there is `ThreadsWait` class, which allows you to wait for any of the threads. Is there anything else on the subject? Is there a way to wait for any of threads/files? – x-yuri Jan 08 '14 at 15:48
  • You've made a reasonable, but incorrect, assumption: because I can find a related question, I'm an expert on the subject. I'm not. :-) Perhaps a reader versed in threads can answer the questions x-yuri's has raised in his/her comment. – Cary Swoveland Jan 08 '14 at 17:10

1 Answers1

2

Don't reinvent the wheel mate :) check out https://github.com/eventmachine/eventmachine (IO lib based on reactor pattern like node.js etc) or (perhaps preferably) https://github.com/celluloid/celluloid-io (IO lib based on actor pattern, better docs and active maintainers)

OPTION 1 - use EM or Celluloid to handle non-blocking sockets

EM and Celluloid are quite different, EM is reactor pattern ("same thing" as node.js, with a threadpool as workaround for blocking calls) and Celluloid is actor pattern (an actor thread pool).

Both can do non-blocking IO to/from a lot of sockets and delegate work to a lot of threads, depending on how you go about to do it. Both libs are very robust, efficient and battle tested, EM has more history but seems to have fallen slightly out of maintenance (https://www.youtube.com/watch?v=mPDs-xQhPb0), celluloid has nicer API and more active community (http://www.youtube.com/watch?v=KilbFPvLBaI).

Best advice I can give is to play with code samples that both projects provide and see what feels best. I'd go with celluloid for a new project, but that's a personal opinion - you may find that EM has more IO-related features (such as handling files, keyboard, unix sockets, ...)

OPTION 2 - use background job queues

I may have been misguided by the low level of your question :) Have you considered using some of the job queues available under ruby? There's a TON of decent and different options available, see https://www.ruby-toolbox.com/categories/Background_Jobs

OPTION 3 - DIY (not recommended)

There is a pure ruby implementation of EM, it uses IO selectables to handle sockets so it offers a pattern for what you're trying to do, check it out: https://github.com/eventmachine/eventmachine/blob/master/lib/em/pure_ruby.rb#L311 (see selectables handling).

However, given the amount of other options, hopefully you shouldn't need to resort to such low level coding.

bbozo
  • 7,075
  • 3
  • 30
  • 56
  • Good point. It's just that I didn't know if there are already invented wheels for the task. Truth be told, I'm not sure if they're a good fit. Or probably I'm not sure how exactly I'm to use them. First, they seem to provide `nodejs`-like paradigm for writing the code. But in `nodejs` you've got callback for every function, that may block execution. With these libraries though, you supposedly put chunks of code which take too long time to execute into a separate thread. Am I taking it right? – x-yuri Jan 08 '14 at 16:04
  • Updated answer again, added DIY and explained celluloid vs EM dillema – bbozo Jan 08 '14 at 21:25
  • Indeed, there are a lot of options. Thanks. The jobs are to be triggered by `HTTP` requests (`sinatra`-based website) and I'm now thinking about simply running them in the background with one of those background jobs gems. And yes, I'm new to `ruby`. It's my first website, that I write in `ruby`. – x-yuri Jan 09 '14 at 16:01