Skip to content

Commit

Permalink
New Promises documentation and updates
Browse files Browse the repository at this point in the history
- 	evaluator of ruby code in markdown files added
- 	document all public methods with YARD (and macros)
- 	hide properly everything private
- 	better OO structure, Future is no longer an Event's child, they share
  	common parent instead, private callback methods simplified
- 	flat_future and flat_event added
- 	schedule fixed on event
- 	CompletableFuture API simplified
- 	removed bad aliases: :complete?, :async
- 	run method added to support green-threads like usage
-	rewrite new MD guide remains
  • Loading branch information
pitr-ch committed Jun 13, 2016
1 parent 23d3cdf commit 3d42ba1
Show file tree
Hide file tree
Showing 8 changed files with 1,393 additions and 772 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ We also have a [mailing list](http://groups.google.com/group/concurrent-ruby) an
#### General-purpose Concurrency Abstractions

* [Async](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Async.html): A mixin module that provides simple asynchronous behavior to a class. Loosely based on Erlang's [gen_server](http://www.erlang.org/doc/man/gen_server.html).
* [Promises Framework](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promises/FutureFactoryMethods.html):
* [Promises Framework](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Promises.html):
Unified implementation of futures and promises which combines features of previous `Future`,
`Promise`, `IVar`, `Event`, `dataflow`, `Delay`, and `TimerTask` into a single framework. It extensively uses the
new synchronization layer to make all the features **non-blocking** and **lock-free**, with the exception of obviously blocking
Expand Down
122 changes: 122 additions & 0 deletions doc/format-md.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
require 'rubygems'
require 'bundler/setup'
require 'pry'
require 'pp'

class MDFormatter

def initialize(input_file, environment)
@input_path = input_file
@environment = environment
@output = ''

process_file input_file
end

def evaluate (code, line)
eval(code, @environment, @input_path, line)
end

def process_ruby(part, start_line)
lines = part.lines
chunks = []
line = ''

while !lines.empty?
line += lines.shift
if Pry::Code.complete_expression? line
chunks << line
line = ''
end
end

raise unless line.empty?

chunk_lines = chunks.map { |chunk| [chunk, [chunk.split($/).size, 1].max] }
indent = 40

line_count = start_line
output = ''
chunk_lines.each do |chunk, lines|
result = evaluate(chunk, line_count)
if chunk.strip.empty? || chunk.include?('#')
output << chunk
else
pre_lines = chunk.lines.to_a
last_line = pre_lines.pop
output << pre_lines.join

if last_line =~ /\#$/
output << last_line.gsub(/\#$/, '')
else
if last_line.size < indent && result.inspect.size < indent
output << "%-#{indent}s %s" % [last_line.chomp, "# => #{result.inspect}\n"]
else
inspect_lines = result.pretty_inspect.lines
output << last_line << "# => #{inspect_lines[0]}" << inspect_lines[1..-1].map { |l| format '# %s', l }.join
end
end
end
line_count += lines
end
output
end

def process_file(input_path)
output_path = input_path.gsub /\.in\.md$/, '.out.md'
input = File.read(input_path)
parts = input.split(/^(```\w*\n)/)

# pp parts.map(&:lines)

code_block = nil
line_count = 1

parts.each do |part|
if part =~ /^```(\w+)$/
code_block = $1
@output << part
line_count += 1
next
end

if part =~ /^```$/
code_block = nil
@output << part
line_count += 1
next
end

if code_block == 'ruby'
@output << process_ruby(part, line_count)
line_count += part.lines.size
next
end

@output << part
line_count += part.lines.size
end

puts "#{input_path}\n -> #{output_path}"
File.write(output_path, @output)
rescue => ex
puts "#{ex} (#{ex.class})\n#{ex.backtrace * "\n"}"

end
end

input_paths = if ARGV.empty?
Dir.glob("#{File.dirname(__FILE__)}/*.in.md")
else
ARGV
end.map { |p| File.expand_path p }

input_paths.each_with_index do |input_path, i|

pid = fork do
require_relative 'init.rb'
MDFormatter.new input_path, binding
end

Process.wait pid
end
7 changes: 7 additions & 0 deletions doc/init.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'concurrent-edge'

def do_stuff
:stuff
end

Concurrent.use_stdlib_logger Logger::DEBUG
49 changes: 39 additions & 10 deletions examples/promises.in.rb → doc/promises.in.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,57 @@
# Adds factory methods like: future, event, delay, schedule, zip, ...
# otherwise they can be called on Promises module
include Concurrent::Promises::FactoryMethods #
# Promises Framework

Promises is a new framework unifying former `Concurrent::Future`, `Concurrent::Promise`, `Concurrent::IVar`,
`Concurrent::Event`, `Concurrent.dataflow`, `Delay`, and `TimerTask`. It extensively uses the new
synchronization layer to make all the features **non-blocking** and
**lock-free**, with the exception of obviously blocking operations like
`#wait`, `#value`. As a result it lowers a danger of deadlocking and offers
better performance.

## Overview

There are two central classes ... TODO

## Where does it executes?

- TODO Explain `_on` `_using` sufixes.

## Old examples follow

*TODO rewrite into md with examples*

### Simple asynchronous task
Adds factory methods like: future, event, delay, schedule, zip, etc. Otherwise
they can be called on Promises module.

```ruby
Concurrent::Promises::FactoryMethods.instance_methods false

include Concurrent::Promises::FactoryMethods #
```

Simple asynchronous task:

```ruby
future = future(0.1) { |duration| sleep duration; :result } # evaluation starts immediately
future.completed?
# block until evaluated
future.value
future.completed?
```

Failing asynchronous task

### Failing asynchronous task

```ruby
future = future { raise 'Boom' }
future.value
future.value! rescue $!
future.reason
# re-raising
raise future rescue $!
```

Direct creation of completed futures

### Direct creation of completed futures

```ruby
succeeded_future(Object.new)
failed_future(StandardError.new("boom"))

Expand Down Expand Up @@ -129,7 +157,7 @@

future.success 1
future.success 1 rescue $!
future.try_success 2
future.success 2, false
event.complete

# The threads can be joined now
Expand Down Expand Up @@ -158,7 +186,7 @@
# executed on :fast executor, only short and non-blocking tasks can go there
future_on(:fast) { 2 }.
# executed on executor for blocking and long operations
then_on(:io) { File.read __FILE__ }.
then_using(:io) { File.read __FILE__ }.
wait


Expand Down Expand Up @@ -288,3 +316,4 @@ def schedule_job(interval, &job)
end #

zip(*concurrent_jobs).value!
```
Loading

0 comments on commit 3d42ba1

Please sign in to comment.