README.md in async-1.0.0 vs README.md in async-1.1.0
- old
+ new
@@ -1,15 +1,16 @@
-# Async
+# ![Async](logo.png)
Async is a composable asynchronous I/O framework for Ruby based on [nio4r] and [timers].
[timers]: https://github.com/socketry/timers
[nio4r]: https://github.com/socketry/nio4r
[![Build Status](https://secure.travis-ci.org/socketry/async.svg)](http://travis-ci.org/socketry/async)
[![Code Climate](https://codeclimate.com/github/socketry/async.svg)](https://codeclimate.com/github/socketry/async)
[![Coverage Status](https://coveralls.io/repos/socketry/async/badge.svg)](https://coveralls.io/r/socketry/async)
+[![Gitter](https://badges.gitter.im/join.svg)](https://gitter.im/socketry/async)
## Motivation
Several years ago, I was hosting websites on a server in my garage. Back then, my ADSL modem was very basic, and I wanted to have a DNS server which would resolve to an internal IP address when the domain itself resolved to my public IP. Thus was born [RubyDNS]. This project [was originally built on](https://github.com/ioquatix/rubydns/tree/v0.8.5) top of [EventMachine], but a lack of support for [IPv6 at the time](https://github.com/ioquatix/rubydns/issues/45) and [other problems](https://github.com/ioquatix/rubydns/issues/14), meant that I started looking for other options. Around that time [Celluloid] was picking up steam. I had not encountered actors before and I wanted to learn more about it. So, [I reimplemented RubyDNS on top of Celluloid](https://github.com/ioquatix/rubydns/tree/v0.9.0) and this eventually became the first stable release.
@@ -39,11 +40,11 @@
$ gem install async
## Usage
-`Async::Reactor` is the top level IO reactor, and runs `Async::Task`s asynchronously. The reactor itself is not thread-safe, so you'd typically have one reactor per thread.
+`Async::Reactor` is the top level IO reactor, and runs multiple tasks asynchronously. The reactor itself is not thread-safe, so you'd typically have [one reactor per thread or process](https://github.com/socketry/async-container).
An `Async::Task` runs using a `Fiber` and blocking operations e.g. `sleep`, `read`, `write` yield control until the operation can succeed.
The design of this core library is deliberately simple in scope. Additional libraries provide asynchronous networking, process management, etc. It's likely you will prefer to depend on `async-io` for actual wrappers around `IO` and `Socket`.
@@ -89,16 +90,16 @@
In order to ensure your resources are cleaned up correctly, make sure you wrap resources appropriately, e.g.:
```ruby
Async::Reactor.run do
+ socket = connect(remote_address) # May raise Async::Stop
+
begin
- socket = connect(remote_address) # May raise Async::Stop so socket could be nil
-
socket.write(...) # May raise Async::Stop
socket.read(...) # May raise Async::Stop
ensure
- socket.close if socket
+ socket.close
end
end
```
As tasks run synchronously until they yield back to the reactor, you can guarantee this model works correctly. While in theory `IO#autoclose` allows you to automatically close file descriptors when they go out of scope via the GC, it may produce unpredictable behavour (exhaustion of file descriptors, flushing data at odd times), so it's not recommended.