Code Monkey home page Code Monkey logo

concurrent-ruby's People

Contributors

adamruzicka avatar ahorek avatar alexanderzagaynov avatar alexdowad avatar anildigital avatar bensheldon avatar billdueber avatar byroot avatar chrisseaton avatar colinsurprenant avatar davishmcclurg avatar eregon avatar fzakaria avatar hanazuki avatar ianks avatar inecas avatar ioquatix avatar ivoanjo avatar jdantonio avatar larskanis avatar lucasallan avatar mastfish avatar meineerde avatar mighe avatar obrok avatar olleolleolle avatar pitr-ch avatar rkday avatar thedrow avatar wildmaples avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

concurrent-ruby's Issues

Failure within critical sections

A while ago we removed Mutex#synchronize in favour of Mutex#lock and #unlock as this is more efficient. Where does this leave us with failure recovering (exceptions etc) inside the critical section? We don't seem to have any tests for this at the moment either.

Migrating yard documentation to githb-pages

Hi guys,

would you agree If I moved our documentation from http://rubydoc.info/ to github pages for this repository?

reasons:

  • I hit an issue which I cannot get around. {include:file:a/path} is not working on rubydoc.info
  • We would have more control over the generated documentation (add plugins, update template).

If you agree I'll create a script which will push the generated documentation from doc directory to github pages. I'll do it in #100 PR with the documentation I am putting together there.

Add a simple STM

Software transactional memory provides a simple model for updating multiple references with atomicity, isolation and consistency. Completely transparent STM in Ruby would require language modifications, but if we have a transactional variable object, we can do it quite easily. This is what Haskell did, with their TVar. Clojure's implementation is similar I believe.

account1 = TVar::new(100_000)
account2 = TVar::new(10)

def transfer(from, to, amount)
  atomically do
    from.modify { |x| x - ammount }
    to.modify { |x| x + amount }
  end
end

The action inside the atomically in transfer either completes or it does not - there's no chance of money being taken from the first account but not appearing in the second, and no chance of someone being able to observe the state where it's been taken from the first and not appeared in the second yet.

This transactional variable approach has a drawback in that we can't provide strong isolation - only weak isolation - that means that if you access the variables outside of an atomically it doesn't work. But don't do that then.

Thoughts?

Atomic IVar

Currently IVar are a bit brittle when shared between many writer threads:

i = IVar.new

Thread.new { i.set(42) }
Thread.new { i.set(43) }

one of them will fail due to MultipleAssignmentError

I was wondering about a safer method like IVar#set_unless_assigned returning true if the operation succeeded, false otherwise.

Given that IVars are a well defined entity in literature, do you think is a good idea to add this method to IVar or should we create a new entity (maybe called AtomicIVar or Probe)?

Intermittently Failing Tests

I'm still trying to address all the intermittently failing tests. It's a Sisyphean task. Please use this thread to link to any failing Travis test runs that you believe are due to buggy tests.

Blocking queue

We have a blocking queue implementation for CRuby and JRuby in Bunny. It's not perfect on CRuby (timeout-based operations is somewhat of a pain to implement on CRuby using only standard library) but JRuby's version is backed by j.u.c.

If you consider it useful enough, I can alter it a bit for your library and submit a pull request.

Wiki outdated

based on #122 discussion, cc @jdantonio

From my experience wiki is always troublesome to keep up to date :/ I think we could move the documents from wiki to our repo and include them to our yard documentation.

Pushing to master?

Hi guys,

I've noticed you are pushing commits directly to master. I would like to suggest an alternative, opening PRs and let all code landing in master go through reviews. So far I had a great experience with PR reviewing. Lot of bugs and problems is discovered through review, it is also a great opportunity to learn form each other.

Source structure

We have a lot of files and their number is going to grow.
We could put them in different folder, repeating what we already did for channels.

Since this refactoring is fairly big, I'd like to hear you opinion

Remove 'leaps of faith' from our constructors

As discussed in #102, assigning ivars in #initialize method does not guarantee their visibility. Following synchronization pattern should be used under JRuby.

  require 'jruby'
  def synchronize
    JRuby.reference0(self).synchronized { yield }
  end

  def initialize
    synchronize do
      # body of the constructor ...
    end
  end

  def a_method
    synchronize do
      # body of a_method ...
    end
  end

Future interface

Future.new takes a block and schedules it, but this strategy can be dangerous because the block can be executed before the end of the constructor, especially if someone subclasses Future

To solve this we can add the method execute that takes a block, returns a Future and then schedules it.
execute can be either a Future method or an external executor one.
The current new method should be deprecated.

Before proceeding, I'd like to know your opinion: changing a public API is never an easy choice :)

v0.6.0 Release Plan and Date

TL;DR I think we should remove ActorContext from the master branch and release 0.6.0 ASAP, possibly as soon as 5/25.

A quick look at the changelog shows that we have implemented a ton of great stuff since the 0.5.0 release. The only thing we're waiting on that was planned for 0.6.0 is a new actor implementation. Since I've changed direction on that (again, more on this later) I think we should remove that from the roadmap for 0.6.0. We've marked the current Actor implementation as deprecated but haven't removed it. We lose nothing if we release 0.6.0 without a new actor implementation, but we deny our community access to many great updates if we continue to hold back.

A further discussion of actors can be found in this thread.

Thoughts?

Actors clear queue at run/stop time

Because actors clear their queue in on_run, there's a race condition where if you try to start a set of actors with a Supervisor and post something to their queue before they get started (or post it before you start them entirely), they drop it on the floor as they start up.

Why do actors clear queue in on_run, on_stop, etc.? In a pooled situation, wouldn't that cause a single restarted worker to blow away the shared mailbox? Maybe there's something I don't understand.

MRI thread pools don't shut down in an orderly fashion

My reading of the docs leads me to believe that the proper way to end use of a thread pool is to call #shutdown followed by #wait_for_termination(seconds).

The following gist demonstrates code that is not deterministic under MRI but works fine under JRuby (although in the case of the latter, I don't know if it's because things are working correctly or that JRuby has other delays that allow the pool time to finish its work.

https://gist.github.com/billdueber/7c9a37ce2c2f09e97b64

I don't understand enough about this to offer a patch, sadly. Just able to identify the problem.

Brittle specs

I saw this when running on JRuby. We should probably fix all brittle tests before 0.6 release.

1) Concurrent::Agent behavior it should behave like observable first notification calls the #update method on all observers without a specified :func
     Failure/Error: latch.count.should eq 0

       expected: 0
            got: 5

       (compared using ==)
     Shared Example Group: "observable" called from ./spec/concurrent/agent_spec.rb:63
     # ./spec/concurrent/observable_shared.rb:128:in `(root)'

I am trying to run it again to get full trace, but so far no luck.

Add support for I-Structures (IVars)

An IVar is like a future that you can assign. As a future is a value that is being computed that you can wait on, an IVar is a value that is waiting to be assigned, that you can wait on. IVars are single assignment and deterministic.

Then, express futures as an asynchronous computation that assigns an IVar. The IVar becomes the primitive on which futures and dataflow are built.

ivar = Concurrent::IVar.new
ivar.set 14
ivar.get
ivar.set 2 # would now be an error

For the theory, see:

Arvind, R. Nikhil, and K. Pingali. I-Structures: Data structures for parallel computing. In Proceedings of Workshop on Graph Reduction, 1986.

For the recent application see DataDrivenFuture in Habanero Java from Rice http://www.cs.rice.edu/~vs3/hjlib/doc/edu/rice/hj/api/HjDataDrivenFuture.html.

use TimerTask to cache ruby function. Need help

re-edit to make the question more clear.

Goal: implementing something like this: asynchronous-http-cache-validations

https://www.igvita.com/2008/10/07/asynchronous-http-cache-validations/

In irb

  def f
      sleep 4 # to simulate a slow database query
      Time.now # return value changes over time to test if TimerTask works
  end

  task = Concurrent::TimerTask.new(execution_interval: 5, timeout_interval: 5) { f }
  task.execute

  # keep calling task.value
  # it never blocks.
  # get updated value periodically

in Sinatra

The function f simulates a query to the backend database. Some slow query takes more than 10 seconds, e.g, popular sales. I can't cache it forever because it changes.

Every user will see the top ranking sales of the day, a dynamically generated list. When the cache expires on that list, it takes more than 10 seconds to re-generate the list. During the 10 seconds, because there's no cache available, every request goes to database.

I am trying the server a stale cache while updating the cache. This can't be done in regular cache engine.

Here is the code

  require 'sinatra'
  require 'concurrent'

    def f
      sleep 4 # to simulate a slow database query
      Time.now # return value changes over time to test if TimerTask works
  end

  task = Concurrent::TimerTask.new(execution_interval: 5, timeout_interval: 5) { f }
  task.execute

  get '/' do
    "#{task.running?} : #{task.value}"
  end

I can't get the task.value updated. Why?

Add support for M-structures (MVars)

An MVar is a mutable single element container. You can store a single item in an MVar, and they're always empty or full. As well as get, you have take, which removes the value. As well as put you have mutate, which atomically takes and puts.

They're basically a value with a mutex.

If you read on an empty MVar you block, if you write to a full MVar, it's an error.

mvar = Concurrent::MVar.new
mvar.put 14
mvar.get
mvar.take
mvar.get # would be an error - it's empty
mvar.put 14
mvar.put 14 # would be an error - it's already full
mvar.mutate { |x| x * 2 }
mvar.get # is now 28

For theory see

P. Barth, R. Nikhil, and Arvind. M-Structures: Extending a parallel, non-strict, functional language with state. In Proceedings of the 5th ACM Conference on Functional Programming Languages and Computer Architecture (FPCA), 1991.

For modern practice, see Haskell's MVar and Scala's SyncVar.

Note that Arvind (third author on that paper) has said he doesn't think they really work - you can get deadlock. But they're still a useful foundation many people are familiar with.

0.6.0 Pre-release 2

We've added several optimizations since the first pre-release of 0.6.0. We should consider another pre-release. Perhaps Friday, May 2.

Thoughts?

Would a SynchronousThreadPool be possible to implement?

For some of our integration tests it would be much simpler if I could set up our futures/etc to use a SynchronousThreadPool which would just execute the block synchronously in the current thread.

Would this be possible or is it just a dumb idea? If the latter, I'd love some pointers on how folks are writing integration tests with concurrent-ruby

Obligation value

Obligation#value waits for the event to occur if timeout is not zero and current state is pending.
Should it wait also if the state is unscheduled?
In other words: should it wait until the obligation is completed, right?

New Actor Implementation Discussion and Roadmap

First, I want to publicly apologize to @lucasallan for changing directions on actors so many times. He has been working very hard to implement remote actors and I keep moving the target. He and I have exchanged thousands of words worth of email messages discussing actors. His contribution to the evolution of this gem are far greater than the commit log indicates. He deserves much thanks.

For the sake of the community it's time for us to document our roadmap for the new actor implementation. We've had several great discussions about actors here, here, here, and here. Petr Chalupa has graciously offered to merge the work he began in his Actress library into our gem and has started the work. I think we all have a fairly consistent vision for how we would like to evolve actors. Let's use this thread to document the roadmap. I'd like to target the 0.7.0 release for the first implementation of new actors.

This roadmap assumes we remove the ActorContext module from the codebase since it was never released (except in a pre-release build).

Below is my attempt to document what I believe we collectively agree on. If I've misunderstood anything we've discussed please correct me. All feedback is welcome.

0.7.0 Initial Actor Implementation

I believe the minimum implementation of a replacement for the original Actor simply needs to provide compatible behavior. Although we plan to add much more, and may include more in 0.7.0, this is what I think should be the bare minimum:

  • Rename Actress to Actor, ActorContext, or something similar. (The current Actor implementation has been deprecated and will be removed. ActorContext was a spike that will be removed.)
  • Factory method #spawn that creates a single actor running on a thread different from the caller (actual threading implementation at the author's discretion)
  • Client's of an actor never have direct access to the actor object. Instead they have access to a "reference" proxy object. The reference prevents clients from making unsafe, unsynchronized method calls directly agains the actor.
  • A non-blocking #tell method which accepts any number of arguments, passes them to the actor/pool for processing, and returns nil. This is a "fire-and-forget" method.
  • A non-blocking #ask method which accepts any number of arguments, passes them to the actor/pool for processing, and returns an IVar which the caller can query for the result or add an observer to.
  • A global "root" actor that provides implicit supervision of actors not otherwise part of hierarchies.
  • (Optional) A block parameter on the #ask method implements the pattern of calling ask then immediately calling #ad_observer with a block on the returned IVar. This would be a convenience method only and would not change the internal message processing of the actor.

Future Features

  • Remote actors which support a pluggable transport proxy.
  • A DRb proxy for remote actors (since DRb is part of the standard library this will be the default transport).
  • (TBD) Factory method #pool that creates multiple actor objects running on a set of threads different from the caller (actual threading implementation at the author's discretion, possibly a thread pool). Actors in the pool will share a virtual "mailbox" such that messages are sent to the pool then delegated to a given actor to process. (NOTE: This may not make sense given the new implementation.)
  • Actor hierarchies with implicit supervision.
  • Actor restart/reset behavior based upon Akka (create a new object when an exception is thrown).
  • Restart strategies "one for one" and "all for one".
  • A global actor registry that allows actors to be referenced by symbolic name.
  • Actor state monitoring as in Akka.
  • (TBD) Akka-inspired become/unbecome hotswapping.
  • (TBD) Type checking and/or pattern matching helpers for message dispatch (see Algebrick and functional-ruby)
  • (TBD) Dead message routing.

TimerTask silently falls through if intervals specified as Strings

If you invoke Concurrent::TimerTask with an execution_interval or timeout_interval that is not an integer, the task never executes nor does it error out.

These values admittedly have no business being strings but the silent nature of the failure took a little bit of time to track down after the introduction of Configliere to manage these parameters in an existing project.

Desired behavior would be to either attempt to convert inputs to ints explicitly or return/raise some sort of invalid argument error.

undefined method `status' for Concurrent::CachedThreadPool and Concurrent::FixedThreadPool

This is happening with CachedThreadPool and FixedThreadPool.

Tested with JRuby 1.7.11 and MRI 1.9.3-p545

NoMethodError: undefined method `status' for #<Concurrent::CachedThreadPool:0x5875de6a>
    from (irb):4:in `evaluate'
    from org/jruby/RubyKernel.java:1121:in `eval'
    from org/jruby/RubyKernel.java:1521:in `loop'
    from org/jruby/RubyKernel.java:1284:in `catch'
    from org/jruby/RubyKernel.java:1284:in `catch'
    from /Users/lucas/.rvm/rubies/jruby-1.7.11/bin/irb:13:in `(root)'
NoMethodError: undefined method `status' for #<Concurrent::FixedThreadPool:0xd1d8e1a>
    from (irb):6:in `evaluate'
    from org/jruby/RubyKernel.java:1121:in `eval'
    from org/jruby/RubyKernel.java:1521:in `loop'
    from org/jruby/RubyKernel.java:1284:in `catch'
    from org/jruby/RubyKernel.java:1284:in `catch'
    from /Users/lucas/.rvm/rubies/jruby-1.7.11/bin/irb:13:in `(root)'

a Promise.all methode ?

Hello,

a little question (but I don't know how to setup the question tag :(

Do you have any plan to implemente a Promise.all method ? I make reference to :

all(promises);
Combines multiple promises into a single promise that is resolved when all of the input promises are resolved. 

from $q of angularJS.

Best regards
Ebuprofen

GitHub wiki vs. project Markdown files

When I started the project I wrote all the documentation in Markdown files in the md directory. Should we deprecate those files and move the content into GitHub wiki pages? It's nice having the documentation in the repo itself but I can't imagine moving the project off of GitHub. The wiki pages may be more usable by the community.

v0.7.0, GitHub Organization, and Merging Atomic

Charles Nutter, aka @headius, has graciously offered to merge his (very successful) ruby-atomic and thread_safe gems into ours. I think we should accept his offer. He has done great work and has been an avid promoter of this gem. If we want to pursue this, we need a plan. Let's use this thread to discuss the roadmap. There are several open issues we need to discuss and make decisions about. Below are my initial thoughts, in no particular order. All input is welcome.

0.6.0 Release

As I discuss in this thread, I think we should release 0.6.0 ASAP. There is a ton of great stuff waiting to be released to the community.

0.7.0 Release Date, with Atomic

I think we should target early August for the release of 0.7.0 with ruby-atomic merged. @headius will be speaking at Steel City Ruby in Pittsburgh, PA on August 15. Pittsburgh is only 2 hours away, by car, from where I live in Akron, OH so I plan to attend (and I've submit a talk proposal so with a little luck I may be speaking, too). This would be a great opportunity to announce the gem merge and promote our work.

Assuming we target this date for the next release, what else should we include? Two things that come to mind immediately (in addition to merging ruby-atomic) are new actors and C extensions.

GitHub Organization

@headius has also suggested we create an organization within GitHub for this gem. As much as I love having my name in the URL, this has become a true team effort. The gem wouldn't be where it is today had I worked alone so I'm happy to move the repo from my personal account to an organization. If we do that, however, we need a name for the organization. Any suggestions?

One Gem, or a Family of Gems

Right now we have about 3,700 lines of code, not counting tests. We plan to extend actors significantly and also merge in up to two additional gems. Has this gem grown too large? The gem composition seems "right" to me because we have a very robust toolkit that is very nicely layered from high-level abstractions (like Async and Future) through mid-level tools (like IVar) down to low-level, optimized utilities (like AtomicFixnum). But we also have a few groups of related functionality that could be pulled out into separate gems. I'm not sure how I feel about keeping everything in one gem versus creating a small family of related gems. My only concern is excessive fragmentation. We could easily do ourselves a disservice if we create too many. One possible way to create multiple gems would be:

  • Atomics
  • Actors (later, once they grow in scope)
  • Everything else

External Dependencies

In another thread we discusses the inclusion of external gem dependencies. We currently have none. My preference is to remain that way. My impression of that discussion is that the majority of the team agree. One result of this discussion was the offer to merge ruby-atomic into our gem. Moving forward we should have consensus on this issue.

Native C and Java Extensions

We've already added several JRuby optimizations and we recently began experimenting with C extensions. We have not made a decision regarding C extensions by my preference is to use them when they make sense. If we merge ruby-atomic into our gem we've answered our question because it has a native C implementation.

One of the greatest strengths of this gem, I believe, is that we have always been interpreter-agnostic. We have pure Ruby implementations of everything. We only use Java to optimize. Our audience is the entire Ruby community, not a subset of it. I believe we should continue with this goal and very diligently follow it.

I do not know if ruby-atomic and thread_safe have pure Ruby implementations. If they do not and we choose to merge them I believe we should update the implementations to follow the "pure Ruby with native optimizations" approach that's served us so well this far.

Pre-release with new thread pools?

On April 9th I will be presenting (remotely) to the Copenhagen Ruby Brigade. I would like to build a pre-release version of the gem before then so that people can start working with the new thread pools. This pre-release will include everything in the changelog up to that point. I would like to build the pre-release on April 8.

The stable version will still be 0.5.0. There is currently no planned release date for stable 0.6.0.

@mighe @chrisseaton @lucasallan Any objections?

0.7.0 Release To-do

This is the to-do list for the 0.7.0 release. The target date for this release is Sunday, 10 August, 2014. This is intended to coincide with the Steel City Ruby conference being help in Pittsburgh, PA, USA on 15-16 August. This is an initial list based on the discussion in Issue #83 ("v0.7.0, GitHub Organization, and Merging Atomic"). Please feel free to add/edit/delete items as necessary.

Organization

Native Extensions

  • Setup the gemspec and extconf.rb files to support C extensions (based on ruby-atomic and the experimental CRuby branches)
  • Setup the gemspec and extconf.rb files to support pure Java extensions (based on ruby-atomic)
  • Update experimental CRuby extensions based on ruby-atomic
    • Remove CEvent (poor performance)
    • Move extensions to root of ext folder
    • Use have_header to set #define
    • Update extsonf.rb to support multiple operating systems
    • Update CAtomicBoolean to support multiple operating systems
    • Update CAtomicFixnum to support multiple operating systems
    • Merge native extension branches into master
  • Merge ruby-atomic
    • Verify compatibility of pure-Ruby, Java, and CRuby versions
    • Move classes into the Concurrent module
    • Rename classes/modules to match existing conventions
  • Add FreeBSD to automated build (reconsider)

New and Updated Abstractions

  • Either deprecate Supervisor and Runnable or update them to use executors and be more thread safe
  • Implement fork-join (move to future release)
  • native JavaEvent (move to future release)

Tests

  • Update RSpec to 3.x
  • Replace all sleep calls in specs with deterministic locking (using CountDownLatch or other atomic variable)
  • Update tests to use ImmediateExecutor when possible
  • Fix brittle specs (see Issue #97)
  • Create stress tests for core classes including
    • Thread pools

Actor

  • fix pending and deadlocking tests
  • better documentation
  • mention add Algebrick and Hamster for messaging
  • 0.6.1 release
  • update old actress gem to point here
  • basic supervision and restarts (:terminate!, :resume!, :reset!, :restart!) #132
  • restart strategies (:one_for_one, :one_for_all) #132
  • dead letter routing #132
  • actor state monitoring as in Akka #132
  • Remove old Actor class
  • Rename Actress to Actor #132
  • Create Actress/Actor alias #132
  • better tests
  • add examples to documentation
  • add example of using Actors with Algebrick and Hamster
  • 0.7 release
  • Remote actors using DRb
  • IO interoperation
  • un/become
  • implement classes similar to Erlang's gen_server, gen_event, and gen_fsm based on supervision. (move to future release)

JRuby warning

Hi, I'm using concurrent-ruby 0.6.0 in JRuby environment and getting strange warning when program starts:

executor.rb:148 warning: ambiguous Java methods found, using submit(java.lang.Runnable)

error installing

I get the following error when trying to install. Any ideas what is causing it?

% ruby --version
ruby 1.9.3p484 (2013-11-22) [x86_64-linux] Brightbox

% bundle install --path vendor
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

/usr/bin/ruby1.9.1 extconf.rb
creating Makefile

make
compiling futures.c
In file included from futures.c:10:0:
/usr/include/ruby-1.9.1/ruby/backward/rubysig.h:14:2: warning: #warning rubysig.h is obsolete [-Wcpp]
#warning rubysig.h is obsolete
^
futures.c:11:20: fatal error: intern.h: No such file or directory
#include "intern.h"
^
compilation terminated.
make: *** [futures.o] Error 1
An error occurred while installing concurrent (0.2.2), and Bundler cannot
continue

RubyMotion?

I'm considering to use concurrent-ruby on some of my projects. For one of them some people are asking me for RubyMotion support and that'd require some work to implement concurrency since I'm already using Celluloid. Since I might take that road that will it make sense to add RubyMotion support for this gem? Or that's way out of the scope?

v1.0.0 Roadmap

The other day @chrisseaton suggested to me that we should begin to plan what 1.0.0 will look like. I think this is an excellent idea. When I started this gem I was just creating a bunch of tools that I thought might be useful. I did not plan a feature set. I am open to all ideas and suggestions. We will use this thread to collectively create a new roadmap.

Below are a few things I would like to accomplish on the way to 1.0.0. These ideas are just a starting point.

Simple, Robust Actors

The actor model is becoming a very popular approach to concurrency. As an Erlang programmer I am partial to Erlang's processes, but they are tightly coupled to features of the Erlang runtime that we can't do in Ruby. I'd like an Actor implementation that supports a couple of key features:

  • Supports both local and remote messaging
  • Pluggable transport layer for remote actor
  • Supports supervision
  • Simple, fluent, and easy to use (no deep coupling and unnecessary internal complexity like many actor frameworks)

More Low Low Level Abstractions

There are many advanced concurrency abstractions in other languages that provide powerful, unique features. These abstractions may not have the broad appeal of Future but they make for an excellent "toolbox" for concurrency. They are also great building blocks for the high level abstractions. I'd like to see more of these in the gem. Some examples include:

More JRuby Optimizations

I hope this gem always remains interpreter-agnostic and I plan to always test against MRI/CRuby, JRuby, and Rubinius, but the JVM is definitely very friendly concurrency/parallelism. We've already implemented a few JVM-specific optimizations (AtomicFixnum and ThreadLocalVar) but I'd like to see us do this as often as possible.

IVar Timeout example

Do you have an example of timeout with ivar ?

if I do
response=Concurrent::IVar.new
v=response.value(1)
sleep(2)

I obtain :
v == nil
response.state == :pending
response.reason == nil

Is it normal ? because response.state == :timeout will be more understable.

TimerSet: cancel/reset task

In my use case I wanted to use a timer to act as a buffer:

  • i queue data
  • I create or reset a timer so that after X seconds an action is performed
  • if the queue reach or exceed a specific size an action is done and the timer is canceled

After looking at the code TimerSet might be my friend using the Concurrent::timer() api passing my actor as an executor instead of using the global pool but what I am missing is a way to cancel/reset (as in restart its countdown).

PS: Looking through the source code is like wandering in a big fair with interesting things everywhere ;)

Implement a wrapper for thread local variables

The current thread local mechanism in Ruby is hard to work with. It's based around symbols, so is hard to isolate different module's variables, and requires slow lookup from symbol to variable.

A wrapper object, ThreadLocalVariable with simple #value and #value= methods would be a useful abstraction. Under MRI and Rubinius it could use the existing mechanism, but allocate a unique symbol automatically. Under JRuby it could directly encapsulate ThreadLocal, without any need for mapping a symbol.

Safe final immutable objects

this is followup to #102 discussion.

In Java if you create an object where all its fields as declared as final than the visibility of those fields is guaranteed (assuming proper construction (which means that references to it do not escape during construction)).

I am looking for a way to properly construct an object in JRuby having similar guaranty assuming any ivar won't be changed after the construction. So it would not need synchronization for every subsequent method call.

From my limited knowledge of Java and JMM I am thinking that the following should work

module GuaranteedVisibility
  require 'jruby'
  java_import 'sun.misc.Unsafe'

  constructor            = Unsafe.java_class.declared_constructor
  constructor.accessible = true
  UNSAFE                 = constructor.new_instance

  def new(*args, &block)
    super *args, &block
    # only Java8
    # http://openjdk.java.net/jeps/171
    # http://stackoverflow.com/questions/23603304/java-8-unsafe-xxxfence-instructions
    UNSAFE.store_fence
  end
end

class ACLass
  extend GuaranteedVisibility
  def initialize
    @a = 'a'
  end
end

AClass.new # guarantees visibility

The store_fence method will ensure that the store_cache on the processor core will be flushed to memory so all other cores will see the latest values. (Same can be done by writing to a volatile field on Java7.)

Next release: v0.5.0 on Monday 17 March 2014?

I've learned that @headius will be talking about this gem during his presentation at RubyConf India on Saturday, 22 March 2014. Because the APIs of Future, ScheduledTask, and Promise (in progress) have changed to include the new #execute method I'd like to release an update prior to his presentation. Unless there is a significant objection from the community I'd like to release version 0.5.0 on Monday, March 17, 2014.

Implement ThreadPoolExecutor.CallerRunsPolicy?

I would love to see an implementation of java's ThreadPoolExecutor.CallerRunsPolicy -- it allows automatic throttling, so I need not worry about creating too big a queue or too many threads when using a thread pool.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.