Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Composable Async Tasks for Clojure

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 src
Octocat-spinner-32 test
Octocat-spinner-32 .gitignore
Octocat-spinner-32 README
Octocat-spinner-32 project.clj
README
# die-geister

Die Geister is a library that provides composable tasks that execute asynchonously.

## Usage

task:
a macro which results in an async task.
geister.core> (task (+ 1 2))
geister.core.Task@aa754f7a
geister.core> @*1
3
geister.core> 

async:
similar to let, but each value in a binding is expected to yield an async task, and
async wraps its body in an implicit (task ...)
geister.core> (async [x (task (+ 1 2))] (+ x 4))
geister.core.Task@90b56cdf
geister.core> @*1
7
geister.core> 

async-loop:
like clojure's built in loop. use async-recur instead of recur. each loop iteration
is queued up as a seperate async task.
geister.core> (async-loop [[x & xs] (range 10) t 0]
               (if x
                (async-recur xs (+ x t))
                t))
geister.core.Task@90ce3f54
geister.core> @*1
45
geister.core> 

async tasks are chainable:
geister.core> (chain (task (+ 1 2)) (fn [x] (task (inc x))))
geister.core.Task@aadbba2f
geister.core> @*1
4
geister.core> 

async tasks are joinable:
geister.core> (join (task (+ 1 2)) (task (+ 3 4)))
geister.core.MultiTask@df4ec6c0
geister.core> @*1
(3 7)
geister.core> 

exceptions are propagated through chains of async tasks. if you deref an async task
and any async tasks that it depended on threw an exception, then that exception will
be thrown.
geister.core> (async [x (task "foo")
                      y (task (+ 1 2))]
                      (+ y x))
geister.core.Task@463b2d3c
geister.core> (try @*1 (catch Exception e (println e)))
#<ClassCastException java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number>
nil
geister.core> 

by default tasks are queued on clojure's pooledExecutor (same as send). you can rebind
*task-handler* to change how and where async tasks are executed.

the TaskProtocol has been extended to futures so you can compose futures with async 
tasks
geister.core> (join (future :foo) (task (+ 2 3)))
geister.core.MultiTask@630cdaf
geister.core> @*1
(:foo 5)
geister.core> 

## Installation

FIXME: write

## Future

remove Task record, just use Future

namespace for doing async IO with tasks

nicer way to schedule tasks to run, perhaps at the namespace level "all tasks in this namespace are run using function X"

## License

Copyright (C) 2010 FIXME

Distributed under the Eclipse Public License, the same as Clojure.
Something went wrong with that request. Please try again.