Project

eldritch

0.09
No commit activity in last 3 years
No release in over 3 years
Adds support for async methods and async blocks. Adds a together block that allows async methods/blocks to be controlled as a group.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.5
~> 11.0
~> 2.14
~> 0.9.11

Runtime

 Project Readme

Eldritch

Build Status Coverage Status Code Climate

The dark arts of concurrent programming.

A DSL that adds parallel programming constructs to make your life a little easier.

Usage

  1. Install it gem install eldritch
  2. Require it require 'eldritch'
  3. Use it (see features below)

By default eldritch will inject the DSL into the global scope. If you don't want this, you can require eldritch/safe instead of eldritch.

require 'eldricth/safe'

class MyClass
  include Eldritch::DSL
  extend Eldritch::DSL

  # The DSL is available in this class
end

Development

Setup

bundler install

Running tests

bundler exec rake

Running examples

ruby -I lib examples/{your favorite example}.rb

Generate doc

bundle exec rake doc

Features

async methods

Async methods run concurrently when called. The caller is returned control right away and the method runs in the background.

require 'eldritch'

# define an async method
async def send_email(email)
  # ...
end

send_email(some_email) # runs in the background

ruby 1.9.3 and 2.0.0

For all versions of ruby before 2.1.0, you need to define async methods like so:

def foo
  # stuff
end
async :foo

Since ruby 2.1.0, def returns the name of the method defined as a symbol. This allows for the cleaner async def foo syntax.

async blocks

Async blocks are run concurrently.

require 'eldritch'

async do
  # runs in the background
end

tasks

Async blocks and async methods both return tasks. These can be used to interact with the async block/method.

require 'eldritch'

task = async do
  # calculate something that will take a long time
end

# we need to result of the task
res = 2 + task.value # waits for the task to finish

together blocks

Together blocks are used to control all async blocks and methods within them as a group. Before exiting, together blocks wait for all their async calls to be done before returning.

require 'eldritch'

together do
  1000.times do
    async do
      # do some work
    end
  end
end
# all 1000 tasks are done

These blocks can also take an argument. This argument is a group that can be used to control the async calls in the block. See the documentation for Eldritch::Group for more information.

require 'eldritch'

together do |group|
  5.times do
    async do
      # do something
      group.interrupt if some_condition  # stops all other tasks
    end
  end
end

A note on GIL

MRI has this nasty little feature called a GIL or Global Interpreter Lock. This lock makes it so that only one thread can run at a time. Let's say that you have 4 cores, running threaded code on MRI will only make use of 1 core. Sometimes, you might not gain a speed boost if you make code parallel. This could the case even if theory says otherwise.

Not all ruby implementations use a GIL. For example, jRuby does not use a GIL.

If your ruby implementation has a GIL, you will probably see a speed boost if your code does a lot of IO or anything that's blocking. In that case running on a single core is not that much of a hindrance, because most of the threads will be blocked and your code should run more often.