[med-svn] [r-cran-future] 01/02: Imported Upstream version 1.0.0

Michael Crusoe misterc-guest at moszumanska.debian.org
Sun Jun 26 00:28:07 UTC 2016


This is an automated email from the git hooks/post-receive script.

misterc-guest pushed a commit to branch master
in repository r-cran-future.

commit 931e601cd0ce0ae3961e59c41d047e7371b438f6
Author: Michael R. Crusoe <crusoe at ucdavis.edu>
Date:   Sat Jun 25 16:31:13 2016 -0700

    Imported Upstream version 1.0.0
---
 DESCRIPTION                                        |  42 +
 MD5                                                | 150 ++++
 NAMESPACE                                          | 105 +++
 NEWS                                               | 273 +++++++
 R/ClusterFuture-class.R                            | 301 +++++++
 R/ClusterRegistry.R                                |  51 ++
 R/ConstantFuture-class.R                           |  23 +
 R/EagerFuture-class.R                              |  27 +
 R/Future-class.R                                   | 360 +++++++++
 R/FutureError-class.R                              |  91 +++
 R/FutureRegistry.R                                 | 100 +++
 R/LazyFuture-class.R                               |  50 ++
 R/MulticoreFuture-class.R                          | 132 +++
 R/MultiprocessFuture-class.R                       |  24 +
 R/MultisessionFuture-class.R                       |  13 +
 R/UniprocessFuture-class.R                         |  74 ++
 R/availableCores.R                                 | 187 +++++
 R/backtrace.R                                      |  35 +
 R/cluster.R                                        |  50 ++
 R/constant.R                                       |   6 +
 R/eager.R                                          |  69 ++
 R/flapply.R                                        |  23 +
 R/future.R                                         |  50 ++
 R/futureAssign.R                                   |  84 ++
 R/futureAssign_OP.R                                |  39 +
 R/futureCall.R                                     |  16 +
 R/futureOf.R                                       | 121 +++
 R/futures.R                                        |  76 ++
 R/globals.R                                        | 200 +++++
 R/lazy.R                                           |  65 ++
 R/mandelbrot.R                                     | 188 +++++
 R/multicore.R                                      | 206 +++++
 R/multiprocess.R                                   |  39 +
 R/multisession.R                                   |  92 +++
 R/nbrOfWorkers.R                                   |  37 +
 R/options.R                                        |  50 ++
 R/plan.R                                           | 208 +++++
 R/plan_OP.R                                        |  25 +
 R/remote.R                                         |  63 ++
 R/resolve.R                                        | 376 +++++++++
 R/resolved.R                                       |  60 ++
 R/signalEarly.R                                    |  44 +
 R/tweak.R                                          |  92 +++
 R/tweakExpression.R                                |  27 +
 R/tweak_OP.R                                       |  29 +
 R/utils.R                                          | 378 +++++++++
 R/values.R                                         |  56 ++
 R/whichIndex.R                                     |  61 ++
 R/zzz.R                                            |  98 +++
 build/vignette.rds                                 | Bin 0 -> 379 bytes
 demo/00Index                                       |   4 +
 demo/fibonacci.R                                   |  30 +
 demo/mandelbrot.R                                  |  94 +++
 inst/doc/future-1-overview.html                    | 881 +++++++++++++++++++++
 inst/doc/future-2-issues.html                      | 447 +++++++++++
 inst/doc/future-2-issues.md.rsp                    | 322 ++++++++
 inst/doc/future-3-topologies.html                  | 367 +++++++++
 inst/doc/future-3-topologies.md.rsp                | 174 ++++
 .../incl/future-1-overview-example2.R              |  20 +
 .../incl/future-1-overview-example3.R              |  19 +
 man/ClusterFuture-class.Rd                         |  50 ++
 man/ConstantFuture-class.Rd                        |  24 +
 man/EagerFuture-class.Rd                           |  39 +
 man/Future-class.Rd                                |  54 ++
 man/FutureError.Rd                                 |  26 +
 man/LazyFuture-class.Rd                            |  39 +
 man/MulticoreFuture-class.Rd                       |  33 +
 man/MultiprocessFuture-class.Rd                    |  33 +
 man/UniprocessFuture-class.Rd                      |  37 +
 man/availableCores.Rd                              |  82 ++
 man/backtrace.Rd                                   |  22 +
 man/cluster.Rd                                     |  87 ++
 man/eager.Rd                                       |  86 ++
 man/future.Rd                                      |  66 ++
 man/future.options.Rd                              |  80 ++
 man/futureAssign.Rd                                |  88 ++
 man/futureOf.Rd                                    |  67 ++
 man/futures.Rd                                     |  29 +
 man/getExpression.Rd                               |  47 ++
 man/grapes-plan-grapes.Rd                          |  22 +
 man/grapes-tweak-grapes.Rd                         |  19 +
 man/lazy.Rd                                        | 113 +++
 man/mandelbrot.Rd                                  |  54 ++
 man/multicore.Rd                                   | 103 +++
 man/multiprocess.Rd                                |  80 ++
 man/multisession.Rd                                | 109 +++
 man/nbrOfWorkers.Rd                                |  20 +
 man/plan.Rd                                        | 143 ++++
 man/remote.Rd                                      |  59 ++
 man/requestCore.Rd                                 |  36 +
 man/resolve.Rd                                     |  44 +
 man/resolved.Rd                                    |  32 +
 man/supportsMulticore.Rd                           |  20 +
 man/tweak.Rd                                       |  28 +
 man/usedCores.Rd                                   |  20 +
 man/value.Rd                                       |  29 +
 man/values.Rd                                      |  25 +
 tests/ClusterRegistry.R                            |  46 ++
 tests/Future-class.R                               |  29 +
 tests/FutureError.R                                |  37 +
 tests/FutureRegistry.R                             | 107 +++
 tests/availableCores.R                             |  77 ++
 tests/backtrace.R                                  |  55 ++
 tests/cluster.R                                    | 191 +++++
 tests/constant.R                                   |  30 +
 tests/demo.R                                       |  29 +
 tests/deprecated.R                                 |  64 ++
 tests/dotdotdot.R                                  |  64 ++
 tests/eager.R                                      |  62 ++
 tests/early-signaling.R                            | 108 +++
 tests/flapply.R                                    |  93 +++
 tests/future.R                                     |  73 ++
 tests/futureAssign.R                               |  43 +
 tests/futureAssign_OP.R                            | 116 +++
 tests/futureAssign_OP_with_environment.R           |  54 ++
 tests/futureAssign_OP_with_listenv.R               |  86 ++
 tests/futureCall.R                                 |  28 +
 tests/futureOf.R                                   |  25 +
 tests/futureOf_with_environment.R                  |  81 ++
 tests/futureOf_with_listenv.R                      | 108 +++
 tests/futures.R                                    | 101 +++
 tests/globals,NSE.R                                |  47 ++
 tests/globals,resolve.R                            |  47 ++
 tests/globals,toolarge.R                           |  39 +
 tests/globals,tricky.R                             |  96 +++
 tests/globalsOf,tweaks.R                           |  44 +
 tests/incl/end.R                                   |  34 +
 tests/incl/start,load-only.R                       |  43 +
 tests/incl/start.R                                 |   2 +
 tests/invalid-owner.R                              |  92 +++
 tests/lazy.R                                       | 112 +++
 tests/mandelbrot.R                                 |  14 +
 tests/multicore.R                                  | 106 +++
 tests/multiprocess.R                               | 133 ++++
 tests/multisession.R                               | 133 ++++
 tests/nbrOfWorkers.R                               |  56 ++
 tests/nested_futures,mc.cores.R                    |  93 +++
 tests/plan.R                                       | 239 ++++++
 tests/remote.R                                     |  54 ++
 tests/requestCore.R                                |  28 +
 tests/requestNode.R                                |  28 +
 tests/resolve.R                                    | 293 +++++++
 tests/rng.R                                        |  94 +++
 tests/startup.R                                    | 238 ++++++
 tests/transparent.R                                |  44 +
 tests/tweak.R                                      | 121 +++
 tests/utils.R                                      | 178 +++++
 tests/uuid.R                                       |  18 +
 tests/whichIndex.R                                 |  77 ++
 vignettes/future-2-issues.md.rsp                   | 322 ++++++++
 vignettes/future-3-topologies.md.rsp               | 174 ++++
 151 files changed, 13975 insertions(+)

diff --git a/DESCRIPTION b/DESCRIPTION
new file mode 100644
index 0000000..4a86308
--- /dev/null
+++ b/DESCRIPTION
@@ -0,0 +1,42 @@
+Package: future
+Version: 1.0.0
+Title: A Future API for R
+Imports: digest, globals (>= 0.6.1), listenv (>= 0.6.0), parallel,
+        utils
+Suggests: R.rsp, markdown
+VignetteBuilder: R.rsp
+Authors at R: c(person("Henrik", "Bengtsson", role=c("aut", "cre", "cph"),
+                                          email = "henrikb at braju.com"))
+Description: A Future API for R is provided. In programming, a future is an
+    abstraction for a value that may be available at some point in the future.
+    The state of a future can either be unresolved or resolved. As soon as it is
+    resolved, the value is available. Futures are useful constructs in for instance
+    concurrent evaluation, e.g. parallel processing and distributed processing on
+    compute clusters. The purpose of this package is to provide a lightweight
+    interface for using futures in R. Functions 'future()' and 'value()' exist for
+    creating futures and requesting their values, e.g.
+    'f <- future({ mandelbrot(-0.75, 0, side=3) })' and 'v <- value(f)'.
+    The 'resolved()' function can be used to check if a future is resolved or not.
+    An infix assignment operator '%<-%' exists for creating futures whose values
+    are accessible by the assigned variables (as promises), e.g.
+    'v %<-% { mandelbrot(-0.75, 0, side=3) }'.
+    This package implements synchronous "lazy" and "eager" futures, and asynchronous
+    "multicore", "multisession" and ad hoc "cluster" futures.
+    Globals variables and functions are automatically identified and exported.
+    Required packages are attached in external R sessions whenever needed.
+    All types of futures are designed to behave the same such that the exact
+    same code work regardless of futures used or number of cores, background
+    sessions or cluster nodes available.
+    Additional types of futures are provided by other packages enhancing
+    this package.
+License: LGPL (>= 2.1)
+LazyLoad: TRUE
+URL: https://github.com/HenrikBengtsson/future
+BugReports: https://github.com/HenrikBengtsson/future/issues
+RoxygenNote: 5.0.1
+NeedsCompilation: no
+Packaged: 2016-06-24 06:16:46 UTC; hb
+Author: Henrik Bengtsson [aut, cre, cph]
+Maintainer: Henrik Bengtsson <henrikb at braju.com>
+Repository: CRAN
+Date/Publication: 2016-06-24 09:53:40
diff --git a/MD5 b/MD5
new file mode 100644
index 0000000..bcf0bfe
--- /dev/null
+++ b/MD5
@@ -0,0 +1,150 @@
+d9e40c76d17986a9c3836805379d874a *DESCRIPTION
+9aaad22d12c436f593215a7446671494 *NAMESPACE
+87c2792323a8f4b24db7bdb69ef6c5d1 *NEWS
+b1e620832f566c83548301d9a6037e3a *R/ClusterFuture-class.R
+f8920b0c54839f391327447172ab6f1d *R/ClusterRegistry.R
+eb7a1d5e5aee29917cd77ab8268911d5 *R/ConstantFuture-class.R
+f621e87dbd5a2963d9b705c7508375bb *R/EagerFuture-class.R
+20f590e4fadca84f2c82d80b6af83f8d *R/Future-class.R
+f4c5670246362c9d233b49e02cefcd8c *R/FutureError-class.R
+f49371755687bb8745bde010f324cde4 *R/FutureRegistry.R
+82d6c3bcf971b00f82918b735217dcdb *R/LazyFuture-class.R
+1239870f0037948407f8f4752efea47d *R/MulticoreFuture-class.R
+4640bc2ba4bd2b94a715b3e9fdd87a0b *R/MultiprocessFuture-class.R
+8e922100c5b70e732c657dfbd50f718b *R/MultisessionFuture-class.R
+cc827eb023a4619ee8813220131b184c *R/UniprocessFuture-class.R
+3fa59f74a7528ed471031225f0abb4b1 *R/availableCores.R
+83e64b9f6e8361620fbea1a6e6377fd9 *R/backtrace.R
+166fc03f07c693854f2f0f6fae0b9414 *R/cluster.R
+adba25fecf647a953f794bd82edfdef2 *R/constant.R
+2dab326b95199f114d8779d59db4b97e *R/eager.R
+b913c5a87fc900714ce598a801904f4f *R/flapply.R
+26aab9bfdae0533bb4643da3779f6021 *R/future.R
+eb912abdea8a4687765ab065483e7067 *R/futureAssign.R
+afe2d79f9142d440aa75121f4cd30767 *R/futureAssign_OP.R
+e652fb677a0fb8c941f07fb8abdb219a *R/futureCall.R
+ee72a50a50b8dfb3ff5fc68cbc8a2245 *R/futureOf.R
+6ddca8968f151063e6797d464ce06722 *R/futures.R
+82fc04c9c34e35ce7c030f6a2e187011 *R/globals.R
+cbf0c52e538bfa95032b8e5283c26078 *R/lazy.R
+58898f5ba92ced1528f31e1db588dbe4 *R/mandelbrot.R
+355e9b89fff62d0cb4ea98d38cc366d6 *R/multicore.R
+00762b0836395a64510237d10bba9954 *R/multiprocess.R
+0e5dc1a8b8109c543ed6764627ca37d4 *R/multisession.R
+09c7e46004ed15f1440c6292322bc60f *R/nbrOfWorkers.R
+960857a106a23b81aab37afdadc14daf *R/options.R
+bc8f221d76bf33c012917333f6fa378c *R/plan.R
+beaf9318ec079559d9c0317c948d171f *R/plan_OP.R
+e695c2a384c9d4640ae3de9bb60dc35c *R/remote.R
+c001e66c0bb0e01b58aa5ccde4dc4a3a *R/resolve.R
+c252cf985ed0c07a3466b1a052534bd6 *R/resolved.R
+341328f9a53c1b529fecb5b34fb4d311 *R/signalEarly.R
+af287c41d84cea82cb1c50506eec5946 *R/tweak.R
+2d209b376b3f82d1f40e90d59a0a9ee6 *R/tweakExpression.R
+1e991bb1d9d9b4da9ed2aa804ada2266 *R/tweak_OP.R
+be19af2eaef024cde2e20b0b5445dd27 *R/utils.R
+e3f4b639a8943fc5c2a2391698df288b *R/values.R
+03874e74c87ddd7a7d4741bb3a411e51 *R/whichIndex.R
+374b97fc18d8ae22e8bb7ab98e8bc664 *R/zzz.R
+ee596936fc45e84d8878cdf6a62ed5e0 *build/vignette.rds
+f615957051c16ab204dab55cf45ec170 *demo/00Index
+d6f69bf0e10c4518df2a9b8b763f66df *demo/fibonacci.R
+a82f2b900b5bdcb20f748c8e2ee9080c *demo/mandelbrot.R
+c783b7227c73fa56028acc6f2f778f80 *inst/doc/future-1-overview.html
+db2774171992c81c9304e585c8d1c3c3 *inst/doc/future-2-issues.html
+5dfc3d022e929e7329c9a758611be00d *inst/doc/future-2-issues.md.rsp
+f66e84c4e10109cca314b9c18cd5920f *inst/doc/future-3-topologies.html
+fc40bba23693cd6d2fad08ffec4bbd59 *inst/doc/future-3-topologies.md.rsp
+d15bee49d2cd9d3c1f2725015a53d7de *inst/vignettes-static/incl/future-1-overview-example2.R
+8bb96c0fa173c00903c0ac2d60b9ecf0 *inst/vignettes-static/incl/future-1-overview-example3.R
+07449dd46b66bef5c07af55261c0f951 *man/ClusterFuture-class.Rd
+be030b72200a4ce93c445904824227ed *man/ConstantFuture-class.Rd
+bdf7f66073dfd6cafcd8d6ada4828fef *man/EagerFuture-class.Rd
+ecf508d4599a169a4be0dbe1043f008c *man/Future-class.Rd
+40336f654bed5785399ac1ee9bd68490 *man/FutureError.Rd
+6925f9764dc51e2fd334c6d76e69558f *man/LazyFuture-class.Rd
+895b649d28573d2a9688d0a8cac1443f *man/MulticoreFuture-class.Rd
+0a0dedf22c1dde0532996727d4eee93a *man/MultiprocessFuture-class.Rd
+66c177978f5cb667434b142e7cd2f578 *man/UniprocessFuture-class.Rd
+5c3f42a10800c70cd8c431d673880f6f *man/availableCores.Rd
+cb2eda9d31a1ca1205e06b710f22fa10 *man/backtrace.Rd
+cd4210ebdbe4b2514bd1dff09490e01f *man/cluster.Rd
+9e8bb991f399fae557e86cdaac2b9817 *man/eager.Rd
+61d11dce702377d1209e34d739be62b6 *man/future.Rd
+2276b91a3ded25763867d78bd586462b *man/future.options.Rd
+e283989bbc01b29fabc73de1200a386e *man/futureAssign.Rd
+3f62c268c306b9e62d4bdb6ee878c9a5 *man/futureOf.Rd
+dc6e43957a22e51eb75414a05a763471 *man/futures.Rd
+bb8e6a67ce3bb99456d0e29b9f4e3985 *man/getExpression.Rd
+e529465059c930c23a2aaab0b370130d *man/grapes-plan-grapes.Rd
+8b94fd9bca4f6d580c623617156388a4 *man/grapes-tweak-grapes.Rd
+fad1eebc76d223ca1a93211bdd2227ce *man/lazy.Rd
+903e8d9c18095f373fa01fce5982296f *man/mandelbrot.Rd
+5505777ea63f279c044c89665f0a6790 *man/multicore.Rd
+d8411f4132ef9a6dd2c4a950fb35ec71 *man/multiprocess.Rd
+5f871fca190eca93f6715f496001738a *man/multisession.Rd
+dccf63069814d5f5d9c88126a1a0c4df *man/nbrOfWorkers.Rd
+e8839e33656f8f151e072bcc6aa074d0 *man/plan.Rd
+bc62470c801c6e0da100a6bcd6f9edaf *man/remote.Rd
+2aaeaddd39794557ad09db552050cc5d *man/requestCore.Rd
+87618eab3429cc479870f7bc842d7e6e *man/resolve.Rd
+215eb769db07713345a571baa6c446b4 *man/resolved.Rd
+e8ecc874982305dc716daa4924c1e72a *man/supportsMulticore.Rd
+0557933001b84a991f7fc1aeabddfcc6 *man/tweak.Rd
+f3a5534c5f7d15e3afdf731874539123 *man/usedCores.Rd
+2ddab805cf905e33c6b477946892208c *man/value.Rd
+a790a5d25c60ba4deeb942596c106399 *man/values.Rd
+21c8e4279c5d3ba6b7f2d74f8f878841 *tests/ClusterRegistry.R
+87185f19d8f8a579c1baa8036c89cd34 *tests/Future-class.R
+46e93ef56ccae2810c50676d6ce61806 *tests/FutureError.R
+7d447970b8fab444805b7f72089999a7 *tests/FutureRegistry.R
+0690c893bcbe7da045f804d41e2976d3 *tests/availableCores.R
+303eca91c90c6920bb0eafd95b691555 *tests/backtrace.R
+8dc90618c5c9e389ad4334a9c210a34b *tests/cluster.R
+a790d6ca23e3fa2dce57372a57c3aa90 *tests/constant.R
+de4a479ed6d1df3a99b38a3f94f3b905 *tests/demo.R
+76989f5f9885e7e7d765303e0657c682 *tests/deprecated.R
+e78ccd5326a90a4fa970c8aa9300128c *tests/dotdotdot.R
+afb76583eb69761924b73716ec8aa084 *tests/eager.R
+b9916ed7b205ade7ce49fb25c7eed477 *tests/early-signaling.R
+93f20e9ec979de1b5f3296035ba63414 *tests/flapply.R
+b56c4d40f7aee9a6ecd9062a199c1454 *tests/future.R
+e624a72b72aaf21840cbdc2ca9566c49 *tests/futureAssign.R
+277c3a9b6d20194991ca02ba7b707e36 *tests/futureAssign_OP.R
+35decab113a7224324ac417f18c6caa3 *tests/futureAssign_OP_with_environment.R
+3a419a0225b64f87f63f60694bc8e345 *tests/futureAssign_OP_with_listenv.R
+7cab3efba3107757628619af161d1a80 *tests/futureCall.R
+3286e4bbf59247ef5d55429271941471 *tests/futureOf.R
+d4085449d7bce6cd1f8a0a150ec3396e *tests/futureOf_with_environment.R
+a17a3e037541a7684208af54799466b2 *tests/futureOf_with_listenv.R
+08e069b25d66347a1bce14d2523d2b67 *tests/futures.R
+78988256e19dcb84233417c4f738375c *tests/globals,NSE.R
+8483856603b3577b011a10dc93251ee6 *tests/globals,resolve.R
+99f71f8f9495a67bf42c3e96e08c6421 *tests/globals,toolarge.R
+1a611ea3faa2a6d4659f36a87af0d555 *tests/globals,tricky.R
+713910223d21a743141a1a0f17d8b013 *tests/globalsOf,tweaks.R
+94920fda0b3bdce0bd00e47e4f479ba5 *tests/incl/end.R
+92e237a767aa5339b945fbb2447b7d12 *tests/incl/start,load-only.R
+3fe5b5d1e7981baf93db9ed2fca8ff2c *tests/incl/start.R
+6e367513d56927f61bdcdc7be385d4ae *tests/invalid-owner.R
+12fb3c6f456b5fca7d7a25d5361621e5 *tests/lazy.R
+ca4e6eac9c74f5ecd0d359100a648ac9 *tests/mandelbrot.R
+74954f2f8bc0201f0feb3f0f303f937a *tests/multicore.R
+20eaee89e2f3b68a8857cd913ddfa4ff *tests/multiprocess.R
+5346fc337fac28eb244b4b359fb74e65 *tests/multisession.R
+f5fa85bf0f0bbe156e973248c5f0c84f *tests/nbrOfWorkers.R
+4749a2c46be45bca5fe2ffa3520682e8 *tests/nested_futures,mc.cores.R
+129a66a6c577584caaf02ca68c1b1d5d *tests/plan.R
+9bfaa25aab33db0330dbe14a6a020328 *tests/remote.R
+e0c9f74a417243e21eabb53f88869cb1 *tests/requestCore.R
+a2fc86b56f77cfc5e401a950b26c5e2e *tests/requestNode.R
+3063292ece2925c5d0249ec938458e23 *tests/resolve.R
+3ff72931949acc03502ed8c3cdde8d6a *tests/rng.R
+dfc7a0d6fd758a74fd2131a93b971357 *tests/startup.R
+aa582dc79e84931929053108ada332a9 *tests/transparent.R
+9f11cb052749aae6ef6306621a80449b *tests/tweak.R
+1424be3086f8e2e09479adf3034e437c *tests/utils.R
+d2c40d881613acc74d63de7bccbefeed *tests/uuid.R
+62d15a52d377ebea7e641406ed990ec9 *tests/whichIndex.R
+5dfc3d022e929e7329c9a758611be00d *vignettes/future-2-issues.md.rsp
+fc40bba23693cd6d2fad08ffec4bbd59 *vignettes/future-3-topologies.md.rsp
diff --git a/NAMESPACE b/NAMESPACE
new file mode 100644
index 0000000..b1902d8
--- /dev/null
+++ b/NAMESPACE
@@ -0,0 +1,105 @@
+# Generated by roxygen2: do not edit by hand
+
+S3method(as.raster,Mandelbrot)
+S3method(futures,environment)
+S3method(futures,list)
+S3method(futures,listenv)
+S3method(getExpression,Future)
+S3method(getExpression,MulticoreFuture)
+S3method(getExpression,MultisessionFuture)
+S3method(getOutput,FutureError)
+S3method(mandelbrot,matrix)
+S3method(mandelbrot,numeric)
+S3method(nbrOfWorkers,"NULL")
+S3method(nbrOfWorkers,future)
+S3method(nbrOfWorkers,multiprocess)
+S3method(nbrOfWorkers,uniprocess)
+S3method(plot,Mandelbrot)
+S3method(print,Future)
+S3method(print,FutureError)
+S3method(resolve,Future)
+S3method(resolve,default)
+S3method(resolve,environment)
+S3method(resolve,list)
+S3method(resolve,listenv)
+S3method(resolved,ClusterFuture)
+S3method(resolved,Future)
+S3method(resolved,LazyFuture)
+S3method(resolved,MulticoreFuture)
+S3method(resolved,default)
+S3method(resolved,environment)
+S3method(resolved,list)
+S3method(tweak,character)
+S3method(tweak,future)
+S3method(value,ClusterFuture)
+S3method(value,Future)
+S3method(value,LazyFuture)
+S3method(value,MulticoreFuture)
+S3method(values,Future)
+S3method(values,environment)
+S3method(values,list)
+S3method(values,listenv)
+export("%->%")
+export("%<-%")
+export("%<=%")
+export("%=>%")
+export("%plan%")
+export("%tweak%")
+export(ClusterFuture)
+export(ConstantFuture)
+export(EagerFuture)
+export(Future)
+export(FutureError)
+export(LazyFuture)
+export(MulticoreFuture)
+export(MultiprocessFuture)
+export(MultisessionFuture)
+export(UniprocessFuture)
+export(availableCores)
+export(backtrace)
+export(cluster)
+export(eager)
+export(future)
+export(futureAssign)
+export(futureCall)
+export(futureOf)
+export(futures)
+export(getExpression)
+export(getOutput)
+export(lazy)
+export(mandelbrot)
+export(mandelbrotTiles)
+export(multicore)
+export(multiprocess)
+export(multisession)
+export(nbrOfWorkers)
+export(plan)
+export(remote)
+export(resolve)
+export(resolved)
+export(supportsMulticore)
+export(transparent)
+export(tweak)
+export(value)
+export(values)
+importFrom(digest,digest)
+importFrom(globals,cleanup)
+importFrom(globals,globalsOf)
+importFrom(globals,packagesOf)
+importFrom(grDevices,as.raster)
+importFrom(grDevices,hsv)
+importFrom(graphics,par)
+importFrom(graphics,plot)
+importFrom(listenv,get_variable)
+importFrom(listenv,listenv)
+importFrom(listenv,map)
+importFrom(listenv,parse_env_subset)
+importFrom(parallel,clusterCall)
+importFrom(parallel,clusterExport)
+importFrom(parallel,makeCluster)
+importFrom(parallel,stopCluster)
+importFrom(utils,capture.output)
+importFrom(utils,file_test)
+importFrom(utils,head)
+importFrom(utils,object.size)
+importFrom(utils,packageVersion)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..f3d2a7a
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,273 @@
+Package: future
+===============
+
+Version: 1.0.0 [2016-06-24]
+o GLOBALS: Falsely identified global variables no longer generate
+  an error when the future is created.  Instead, we leave it to R
+  and the evaluation of the individual futures to throw an error
+  if the a global variable is truly missing.  This was done in order
+  to automatically handle future expressions that use non-standard
+  evaluation (NSE), e.g. subset(df, x < 3) where 'x' is falsely
+  identified as a global variable.
+o Add support for remote(..., myip="<external>"), which now
+  queries a set of external lookup services in case one of them
+  fails.
+o DEMO: Now the Mandelbrot demo tiles a single Mandelbrot region
+  with one future per tile. This better illustrates parallelism.
+o Add mandelbrot() function used in demo to the API for convenience.
+o DOCUMENTATION: Documented R options used by the future package.
+o ROBUSTNESS: If .future.R script, which is sourced when the future
+  package is attached, gives an error, then the error is ignored
+  with a warning.
+o CLEANUP: Dropped support for system environment variable
+  'R_FUTURE_GLOBALS_MAXSIZE'.
+o TROUBLESHOOTING: If the future requires attachment of packages,
+  then each namespace is loaded separately and before attaching
+  the package.  This is done in order to see the actual error
+  message in case there is a problem while loading the namespace.
+  With require()/library() this error message is otherwise suppressed
+  and replaced with a generic one.
+o BUG FIX: Custom futures based on a constructor function that
+  is defined outside a package gave an error.
+o BUG FIX: plan("default") assumed that the 'future.plan' option
+  was a string; gave an error if it was a function.
+o BUG FIX: Various future options were not passed on to futures.
+o BUG FIX: A startup .future.R script is no longer sourced if the
+  future package is attached by a future expression.
+
+
+Version: 0.15.0 [2016-06-13]
+o Now .future.R (if found in the current directory or otherwise in
+  the user's home directory) is sourced when the future package is
+  attach (but not loaded).  This helps separating scripts from
+  configuration of futures.
+o Added remote futures, which are cluster futures with convenient
+  default arguments for simple remote access to R, e.g.
+  plan(remote, workers="login.my-server.org").
+o Added support for plan(cluster, workers=c("n1", "n2", "n2", "n4")),
+  where 'workers' (also for ClusterFuture()) is a set of host names
+  passed to parallel::makeCluster(workers).  It can also be the number
+  of localhost workers.
+o Added command line option --parallel=<p>, which is long for -p <p>.
+o Now command line option -p <p> also set the default future strategy
+  to multiprocessing (if p >= 2 and eager otherwise), unless another
+  strategy is already specified via option 'future.plan' or system
+  environment variable R_FUTURE_PLAN.
+o Now availableCores() also acknowledges environment variable NSLOTS
+  set by Sun/Oracle Grid Engine (SGE).
+o MEMORY: Added argument 'gc=FALSE' to all futures.  When TRUE, the
+  garbage collector will run at the very end in the process that
+  evaluated the future (just before returning the value).  This may
+  help lowering the overall memory footprint when running multiple
+  parallel R processes.  The user can enable this by specifying
+  plan(multiprocess, gc=TRUE).  The developer can control this using
+  future(expr, gc=TRUE) or v %<-% { expr } %tweak% list(gc=TRUE).
+o SPEEDUP: Significantly decreased the overhead of creating a future,
+  particularly multicore futures.
+o BUG FIX: Future would give an error with plan(list("eager")),
+  whereas it did work with plan("eager") and plan(list(eager)).
+
+
+Version: 0.14.0 [2016-05-16]
+o Renamed arguments 'maxCores' and 'cluster' to 'workers'.  If using
+  the old argument names a deprecation warning will be generated, but
+  it will still work until made defunct in a future release.
+o Added nbrOfWorkers().
+o values() passes arguments '...' to value() of each Future.
+o Added FutureError class.
+o Added informative print() method for the Future class.
+o BUG FIX: resolve() for lists and environments did not work
+  properly when the set of futures was not resolved in order,
+  which could happen with asynchronous futures.
+
+
+Version: 0.13.0 [2016-04-13]
+o Add support to plan() for specifying different future strategies for
+  the different levels of nested futures.
+o Add backtrace() for listing the trace the expressions evaluated (the
+  calls made) before a condition was caught.
+o Add transparent futures, which are eager futures with early signaling
+  of conditioned enabled and whose expression is evaluated in the calling
+  environment.  This makes the evaluation of such futures as similar
+  as possible to how R evaluates expressions, which in turn simplifies
+  troubleshooting errors etc.
+o Add support for early signaling of conditions.  The default is
+  (as before) to signal conditions when the value is queried.
+  In addition, they may be signals as soon as possible, e.g. when
+  checking whether a future is resolved or not.
+o Signaling of conditions when calling value() is now controlled by
+  argument 'signal' (previously 'onError').
+o Now UniprocessFuture:s captures the call stack for errors occurring
+  while resolving futures.
+o ClusterFuture gained argument 'persistent=FALSE'.  With persistent=TRUE,
+  any objects in the cluster R session that was created during the
+  evaluation of a previous future is available for succeeding futures
+  that are evaluated in the same session.  Moreover, globals are
+  still identified and exported but "missing" globals will not give
+  an error - instead it is assumed such globals are available in the
+  environment where the future is evaluated.
+o OVERHEAD: Utility functions exported by ClusterFuture are now much
+  smaller; previously they would export all of the package environment.
+o BUG FIX: f <- multicore(NA, maxCores=2) would end up in an endless
+  waiting loop for a free core if availableCores() returned one.
+o BUG FIX: ClusterFuture would ignore local=TRUE.
+
+
+Version: 0.12.0 [2016-02-23]
+o Added multiprocess futures, which are multicore futures if supported,
+  otherwise multisession futures.  This makes it possible to use
+  plan(multiprocess) everywhere regardless of operating system.
+o Future strategy functions gained class attributes such that it is
+  possible to test what type of future is currently used, e.g.
+  inherits(plan(), "multicore").
+o ROBUSTNESS: It is only the R process that created a future that can
+  resolve it. If a non-resolved future is queried by another R process,
+  then an informative error is generated explaining that this is not
+  possible.
+o ROBUSTNESS: Now value() for multicore futures detects if the underlying
+  forked R process was terminated before completing and if so generates
+  an informative error messages.
+o SPEED: Adjusted the parameters for the schema used to wait for next
+  available cluster node such that nodes are polled more frequently.
+o GLOBALS: resolve() gained argument 'recursive'.
+o GLOBALS: Added option 'future.globals.resolve' for controlling whether
+  global variables should be resolved for futures or not.  If TRUE, then
+  globals are searched recursively for any futures and if found such
+  "global" futures are resolved.  If FALSE, global futures are not
+  located, but if they are later trying to be resolved by the parent
+  future, then an informative error message is generated clarifying
+  that only the R process that created the future can resolve it.
+  The default is currently FALSE.
+o FIX: Exports of objects available in packages already attached
+  by the future were still exported.
+o FIX: Now availableCores() returns 3L (=2L+1L) instead of 2L
+  if _R_CHECK_LIMIT_CORES_ is set.
+
+
+Version: 0.11.0 [2016-01-15]
+o GLOBALS: All futures now validates globals by default (globals=TRUE).
+o Add multisession futures, which analogously to multicore ones,
+  use multiple cores on the local machine with the difference
+  that they are evaluated in separate R session running in the
+  background rather than separate forked R processes.
+  A multisession future is a special type of cluster futures that
+  do not require explicit setup of cluster nodes.
+o Add support for cluster futures, which can make use of a cluster
+  of nodes created by parallel::makeCluster().
+o Add futureCall(), which is for futures what do.call() is otherwise.
+o Standardized how options are named, i.e. 'future.<option>'.
+  If you used any future options previously, make sure to check
+  they follow the above format.
+
+
+Version: 0.10.0 [2015-12-30]
+o Now %<=% can also assign to multi-dimensional list environments.
+o Add futures(), values() and resolved().
+o Add resolve() to resolve futures in lists and environments.
+o Now availableCores() also acknowledges the number of CPUs
+  allotted by Slurm.
+o CLEANUP: Now the internal future variable created by %<=% is
+  removed when the future variable is resolved.
+o BUG FIX: futureOf(envir=x) did not work properly when 'x' was
+  a list environment.
+
+
+Version: 0.9.0 [2015-12-11]
+o GLOBALS: Now globals ("unknown" variables) are identified
+  using the new findGlobals(..., method="ordered") in
+  globals (> 0.5.0) such that a global variable preceding
+  a local variable with the same name is properly identified
+  and exported/frozen.
+o DOCUMENTATION: Updated vignette on common issues with the
+  case where a global variable is not identified because it
+  is hidden by an element assignment in the future expression.
+o ROBUSTNESS: Now values of environment variables are trimmed
+  before being parsed.
+o ROBUSTNESS: Add reproducibility test for random number
+  generation using Pierre L'Ecuyer's RNG stream regardless
+  of how futures are evaluated, e.g. eager, lazy and multicore.
+o BUG FIX: Errors occurring in multicore futures could prevent
+  further multicore futures from being created.
+
+
+Version: 0.8.2 [2015-10-14]
+o BUG FIX: Globals that were copies of package objects
+  were not exported to the future environments.
+o BUG FIX: The future package had to be attached or
+  future::future() had to be imported, if %<=% was used
+  internally in another package.  Similarly, it also had
+  to be attached if multicore futures where used.
+
+
+Version: 0.8.1 [2015-10-05]
+o eager() and multicore() gained argument 'globals', where
+  globals=TRUE will validate that all global variables
+  identified can be located already before the future is
+  created.  This provides the means for providing the same
+  tests on global variables with eager and multicore futures
+  as with lazy futures.
+o lazy(sum(x, ...), globals=TRUE) now properly passes `...`
+  from the function from which the future is setup.  If not
+  called within a function or called within a function without
+  `...` arguments, an informative error message is thrown.
+o Added vignette 'Futures in R: Common issues with solutions'.
+
+
+Version: 0.8.0 [2015-09-06]
+o plan("default") resets to the default strategy, which is
+  synchronous eager evaluation unless option 'future_plan'
+  or environment variable 'R_FUTURE_PLAN' has been set.
+o availableCores("mc.cores") returns getOption("mc.cores") + 1L,
+  because option 'mc.cores' specifies "allowed number of _additional_
+  R processes" to be used in addition to the main R process.
+o BUG FIX: plan(future::lazy) and similar gave errors.
+
+
+Version: 0.7.0 [2015-07-13]
+o ROBUSTNESS: multicore() blocks until one of the CPU cores
+  is available, iff all are currently occupied by other
+  multicore futures.
+o multicore() gained argument 'maxCores', which makes it
+  possible to use for instance plan(multicore, maxCores=4L).
+o Add availableMulticore() [from (in-house) 'async' package].
+o More colorful demo("mandelbrot", package="future").
+o BUG FIX: old <- plan(new) now returns the old plan/strategy
+  (was the newly set one).
+
+
+Version: 0.6.0 [2015-06-18]
+o Add multicore futures, which are futures that are resolved
+  asynchronously in a separate process.  These are only
+  supported on Unix-like systems, but not on Windows.
+
+
+Version: 0.5.1 [2015-06-18]
+o Eager and lazy futures now records the result internally
+  such that the expression is only evaluated once, even if
+  their errored values are requested multiple times.
+o Eager futures are always created regardless of error or not.
+o All Future objects are environments themselves that record
+  the expression, the call environment and optional variables.
+
+
+Version: 0.5.0 [2015-06-16]
+o lazy() "freezes" global variables at the time when
+  the future is created.  This way the result of a lazy
+  future is more likely to be the same as an eager future.
+  This is also how globals are likely to be handled by
+  asynchronous futures.
+
+
+Version: 0.4.2 [2015-06-15]
+o plan() records the call.
+o Added demo("mandelbrot", package="future"), which can be
+  re-used by other future packages.
+
+
+Version: 0.4.1 [2015-06-14]
+o Added plan().
+o Added eager future - useful for troubleshooting.
+
+
+Version: 0.4.0 [2015-06-07]
+o Distilled Future API from (in-house) 'async' package.
diff --git a/R/ClusterFuture-class.R b/R/ClusterFuture-class.R
new file mode 100644
index 0000000..2ee8f1f
--- /dev/null
+++ b/R/ClusterFuture-class.R
@@ -0,0 +1,301 @@
+#' A cluster future is a future whose value will be resolved asynchroneously in a parallel process
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE).
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param local If TRUE, the expression is evaluated such that
+#' all assignments are done to local temporary environment, otherwise
+#' the assignments are done in the global environment of the cluster node.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param persistent If FALSE, the evaluation environment is cleared
+#' from objects prior to the evaluation of the future.
+#' @param workers A \code{\link[parallel:makeCluster]{cluster}}.
+#' Alternatively, a character vector of host names or a numeric scalar,
+#' for creating a cluster via \code{\link[parallel]{makeCluster}(workers)}.
+#' @param \dots Additional named elements of the future.
+#'
+#' @return An object of class \code{ClusterFuture}.
+#'
+#' @seealso
+#' To evaluate an expression using "cluster future", see function
+#' \code{\link{cluster}()}.
+#'
+#' @aliases MultisessionFuture MultisessionFuture-class
+#' @export
+#' @export MultisessionFuture
+#' @importFrom digest digest
+#' @name ClusterFuture-class
+#' @keywords internal
+ClusterFuture <- function(expr=NULL, envir=parent.frame(), substitute=FALSE, local=!persistent, gc=!persistent, persistent=FALSE, workers=NULL, ...) {
+  defaultCluster <- importParallel("defaultCluster")
+
+  ## BACKWARD COMPATIBILITY
+  args <- list(...)
+  if ("cluster" %in% names(args)) {
+    workers <- args$cluster
+    .Deprecated(msg="Argument 'cluster' has been renamed to 'workers'. Please update your script/code that uses the future package.")
+  }
+
+  if (substitute) expr <- substitute(expr)
+
+  if (is.null(workers)) {
+    workers <- defaultCluster()
+  } else if (is.character(workers) || is.numeric(workers)) {
+    workers <- ClusterRegistry("start", workers=workers)
+  } else if (!inherits(workers, "cluster")) {
+    stop("Argument 'workers' is not of class 'cluster': ", class(workers)[1])
+  }
+  stopifnot(length(workers) > 0)
+
+  ## Attach name to cluster?
+  name <- attr(workers, "name")
+  if (is.null(name)) {
+    name <- digest(workers)
+    stopifnot(length(name) > 0, nzchar(name))
+    attr(workers, "name") <- name
+  }
+
+  gp <- getGlobalsAndPackages(expr, envir=envir, persistent=persistent)
+
+  f <- MultiprocessFuture(expr=gp$expr, envir=envir, substitute=FALSE, local=local, persistent=persistent, globals=gp$globals, packages=gp$packages, workers=workers, node=NA_integer_, ...)
+  structure(f, class=c("ClusterFuture", class(f)))
+}
+
+
+
+#' @importFrom parallel clusterCall clusterExport
+run.ClusterFuture <- function(future, ...) {
+  ## Assert that the process that created the future is
+  ## also the one that evaluates/resolves/queries it.
+  assertOwner(future)
+
+  sendCall <- importParallel("sendCall")
+  workers <- future$workers
+  expr <- getExpression(future)
+  persistent <- future$persistent
+
+  ## FutureRegistry to use
+  reg <- sprintf("workers-%s", attr(workers, "name"))
+
+
+  ## Next available cluster node
+  node <- requestNode(await=function() {
+    mdebug("Waiting for free cluster node ...")
+    FutureRegistry(reg, action="collect-first")
+    mdebug("Waiting for free cluster node ... DONE")
+  }, workers=workers)
+  future$node <- node
+
+  ## Cluster node to use
+  cl <- workers[node]
+
+
+  ## WORKAROUND: When running covr::package_coverage(), the
+  ## package being tested may actually not be installed in
+  ## library path used by covr.  We here add that path iff
+  ## covr is being used. /HB 2016-01-15
+  if (is.element("covr", loadedNamespaces())) {
+    mdebug("covr::package_coverage() workaround ...")
+    libPath <- .libPaths()[1]
+    clusterCall(cl, fun=function() .libPaths(c(libPath, .libPaths())))
+    mdebug("covr::package_coverage() workaround ... DONE")
+  }
+
+
+  ## (i) Reset global environment of cluster node such that
+  ##     previous futures are not affecting this one, which
+  ##     may happen even if the future is evaluated inside a
+  ##     local, e.g. local({ a <<- 1 }).
+  if (!persistent) {
+    clusterCall(cl, fun=grmall)
+  }
+
+
+  ## (ii) Attach packages that needs to be attached
+  packages <- future$packages
+  if (length(packages) > 0) {
+    mdebug("Attaching %d packages (%s) on cluster node #%d ...",
+                    length(packages), hpaste(sQuote(packages)), node)
+
+    clusterCall(cl, fun=requirePackages, packages)
+
+    mdebug("Attaching %d packages (%s) on cluster node #%d ... DONE",
+                    length(packages), hpaste(sQuote(packages)), node)
+  }
+
+
+  ## (iii) Export globals
+  globals <- future$globals
+  if (length(globals) > 0) {
+    for (name in names(globals)) {
+      ## For instance sendData.SOCKnode(...) may generate warnings
+      ## on packages not being available after serialization, e.g.
+      ##  In serialize(data, node$con) :
+      ## package:future' may not be available when loading
+      ## Here we'll suppress any such warnings.
+      mdebug("Exported %s to cluster node #%d ...", sQuote(name), node)
+      suppressWarnings({
+        clusterCall(cl, fun=gassign, name, globals[[name]])
+      })
+      mdebug("Exported %s to cluster node #%d ... DONE", sQuote(name), node)
+    }
+  }
+  ## Not needed anymore
+  globals <- NULL
+
+
+  ## Add to registry
+  FutureRegistry(reg, action="add", future=future, earlySignal=FALSE)
+
+  ## (iv) Launch future
+  sendCall(cl[[1L]], fun=geval, args=list(expr))
+
+  future$state <- 'running'
+
+  invisible(future)
+}
+
+#' @export
+resolved.ClusterFuture <- function(x, timeout=0.2, ...) {
+  ## Is future even launched?
+  if (x$state == 'created') return(FALSE)
+
+  ## Is value already collected?
+  if (x$state %in% c('finished', 'failed', 'interrupted')) return(TRUE)
+
+  ## Assert that the process that created the future is
+  ## also the one that evaluates/resolves/queries it.
+  assertOwner(x)
+
+  workers <- x$workers
+  node <- x$node
+  cl <- workers[node]
+
+  ## Check if workers socket connection is available for reading
+  con <- cl[[1]]$con
+  res <- socketSelect(list(con), write=FALSE, timeout=timeout)
+
+  ## Signal conditions early? (happens only iff requested)
+  if (res) signalEarly(x, ...)
+
+  res
+}
+
+#' @export
+value.ClusterFuture <- function(future, ...) {
+  ## Has the value already been collected?
+  if (future$state %in% c('finished', 'failed', 'interrupted')) {
+    return(NextMethod("value"))
+  }
+
+  ## Assert that the process that created the future is
+  ## also the one that evaluates/resolves/queries it.
+  assertOwner(future)
+
+  recvResult <- importParallel("recvResult")
+
+  workers <- future$workers
+  node <- future$node
+  cl <- workers[node]
+
+  ## If not, wait for process to finish, and
+  ## then collect and record the value
+  ack <- tryCatch({
+    res <- recvResult(cl[[1]])
+    TRUE
+  }, simpleError = function(ex) ex)
+
+  if (inherits(ack, "simpleError")) {
+    ex <- FutureError(sprintf("Failed to retrieve the value of %s from cluster node #%d on %s.  The reason reported was %s", class(future)[1], node, cl$host, sQuote(ack$message)), call=ack$call, future=future)
+    stop(ex)
+  }
+  stopifnot(isTRUE(ack))
+
+  ## An error?
+  if (inherits(res, "try-error")) {
+    msg <- simpleError(res)
+    mdebug("Received error on future: %s", sQuote(msg))
+    attr(res, "condition") <- msg
+  }
+
+  ## Update value and state
+  condition <- attr(res, "condition")
+  if (inherits(condition, "simpleError")) {
+    future$state <- 'failed'
+    future$value <- condition
+  } else {
+    future$value <- res
+    future$state <- 'finished'
+  }
+  res <- NULL ## Not needed anymore
+
+  ## FutureRegistry to use
+  reg <- sprintf("workers-%s", attr(workers, "name"))
+
+  ## Remove from registry
+  FutureRegistry(reg, action="remove", future=future, earlySignal=FALSE)
+
+  NextMethod("value")
+}
+
+
+requestNode <- function(await, workers, times=getOption("future.wait.times", 600L), delta=getOption("future.wait.interval", 0.001), alpha=getOption("future.wait.alpha", 1.01)) {
+  stopifnot(is.function(await))
+  stopifnot(inherits(workers, "cluster"))
+  times <- as.integer(times)
+  stopifnot(is.finite(times), times > 0)
+  stopifnot(is.finite(alpha), alpha > 0)
+
+  ## Maximum number of nodes available
+  total <- length(workers)
+
+  ## FutureRegistry to use
+  reg <- sprintf("workers-%s", attr(workers, "name"))
+
+  usedNodes <- function() {
+    ## Number of unresolved cluster futures
+    length(FutureRegistry(reg, action="list", earlySignal=FALSE))
+  }
+
+
+  iter <- 1L
+  interval <- delta
+  finished <- FALSE
+  while (iter <= times) {
+    finished <- (usedNodes() < total)
+    if (finished) break
+
+    ## Wait
+    Sys.sleep(interval)
+
+    ## Finish/close workers, iff possible
+    await()
+
+    interval <- alpha*interval
+    iter <- iter + 1L
+  }
+
+  if (!finished) {
+    msg <- sprintf("TIMEOUT: All %d workers are still occupied", total)
+    mdebug(msg)
+    stop(msg)
+  }
+
+  ## Find which node is available
+  avail <- rep(TRUE, times=length(workers))
+  futures <- FutureRegistry(reg, action="list", earlySignal=FALSE)
+  nodes <- unlist(lapply(futures, FUN=function(f) f$node))
+  avail[nodes] <- FALSE
+
+  ## Sanity check
+  stopifnot(any(avail))
+
+  node <- which(avail)[1L]
+  stopifnot(is.numeric(node), is.finite(node), node >= 1)
+
+  node
+}
+
diff --git a/R/ClusterRegistry.R b/R/ClusterRegistry.R
new file mode 100644
index 0000000..7d08bb7
--- /dev/null
+++ b/R/ClusterRegistry.R
@@ -0,0 +1,51 @@
+#' @importFrom parallel makeCluster stopCluster
+#' @importFrom utils capture.output
+ClusterRegistry <- local({
+  last <- NULL
+  cluster <- NULL
+
+  .makeCluster <- function(workers, ...) {
+    if (is.null(workers)) return(NULL)
+    capture.output({
+      cluster <- makeCluster(workers, ...)
+    })
+    cluster
+  }
+
+  function(action=c("get", "start", "stop"), workers=NULL, ...) {
+    action <- match.arg(action)
+
+    if (is.null(workers)) {
+    } else if (is.numeric(workers)) {
+      workers <- as.integer(workers)
+      stopifnot(length(workers) == 1, is.finite(workers))
+    } else if (is.character(workers)) {
+      stopifnot(length(workers) >= 1, !anyNA(workers))
+      workers <- sort(workers)
+    } else {
+      stop("Unknown mode of argument 'workers': ", mode(workers))
+    }
+
+    if (is.null(cluster) && action != "stop") {
+      cluster <<- .makeCluster(workers, ...)
+      last <<- workers
+    }
+
+    if (action == "get") {
+      return(cluster)
+    } else if (action == "start") {
+      ## Already setup?
+      if (!identical(workers, last)) {
+        ClusterRegistry(action="stop")
+        cluster <<- .makeCluster(workers, ...)
+        last <<- workers
+      }
+    } else if (action == "stop") {
+      if (!is.null(cluster)) try(stopCluster(cluster), silent=TRUE)
+      cluster <<- NULL
+      last <<- NULL
+    }
+
+    invisible(cluster)
+  }
+}) ## ClusterRegistry()
diff --git a/R/ConstantFuture-class.R b/R/ConstantFuture-class.R
new file mode 100644
index 0000000..f0d7961
--- /dev/null
+++ b/R/ConstantFuture-class.R
@@ -0,0 +1,23 @@
+#' A future with a constant value
+#'
+#' A constant future is a future whose expression is a constant
+#' and therefore already resolved upon creation
+#'
+#' @param expr An R value.
+#' @param \dots Not used.
+#'
+#' @return An object of class \code{ConstantFuture}.
+#'
+#' @export
+#' @name ConstantFuture-class
+#' @keywords internal
+ConstantFuture <- function(expr=NULL, envir=emptyenv(), substitute=FALSE, local=FALSE, gc=FALSE, ...) {
+  expr <- force(expr)
+  f <- Future(expr=expr, envir=emptyenv(), substitute=FALSE, local=FALSE, gc=FALSE, ...)
+  f$value <- expr
+  f$state <- "finished"
+  structure(f, class=c("ConstantFuture", class(f)))
+  f
+}
+
+evaluate.ConstantFuture <- function(future, ...) future
diff --git a/R/EagerFuture-class.R b/R/EagerFuture-class.R
new file mode 100644
index 0000000..4af322a
--- /dev/null
+++ b/R/EagerFuture-class.R
@@ -0,0 +1,27 @@
+#' An eager future is a future whose value will be resolved immediately
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE).
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param local If TRUE, the expression is evaluated such that
+#' all assignments are done to local temporary environment, otherwise
+#' the assignments are done in the calling environment.
+#' @param gc If TRUE, the garbage collector run after the future is resolved.
+#' @param \dots Additional named elements of the future.
+#'
+#' @return An object of class \code{EagerFuture}.
+#'
+#' @seealso
+#' To evaluate an expression using "eager future", see function
+#' \code{\link{eager}()}.
+#'
+#' @export
+#' @name EagerFuture-class
+#' @keywords internal
+EagerFuture <- function(expr=NULL, envir=parent.frame(), substitute=FALSE, local=TRUE, gc=FALSE, ...) {
+  if (substitute) expr <- substitute(expr)
+  f <- UniprocessFuture(expr=expr, envir=envir, substitute=FALSE, local=local, gc=gc, ...)
+  structure(f, class=c("EagerFuture", class(f)))
+}
diff --git a/R/Future-class.R b/R/Future-class.R
new file mode 100644
index 0000000..b520656
--- /dev/null
+++ b/R/Future-class.R
@@ -0,0 +1,360 @@
+#' A future represents a value that will be available at some point in the future
+#'
+#' A \emph{future} is an abstraction for a \emph{value} that may
+#' available at some point in the future.  A future can either be
+#' \code{unresolved} or \code{resolved}, a state which can be checked
+#' with \code{\link{resolved}()}.  As long as it is \emph{unresolved}, the
+#' value is not available.  As soon as it is \emph{resolved}, the value
+#' is available via \code{\link[future]{value}()}.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE).
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param local If TRUE, the expression is evaluated such that
+#' all assignments are done to local temporary environment, otherwise
+#' the assignments are done in the calling environment.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param earlySignal Specified whether conditions should be signaled
+#' as soon as possible or not.
+#' @param \dots Additional named elements of the future.
+#'
+#' @return An object of class \code{Future}.
+#'
+#' @details
+#' A Future object is itself an \link{environment}.
+#'
+#' @seealso
+#' One function that creates a Future is \code{\link{future}()}.
+#' It returns a Future that evaluates an R expression in the future.
+#' An alternative approach is to use the \code{\link{\%<=\%}} infix
+#' assignment operator, which creates a future from the
+#' right-hand-side (RHS) R expression and assigns its future value
+#' to a variable as a \emph{\link[base]{promise}}.
+#'
+#' @export
+#' @name Future-class
+Future <- function(expr=NULL, envir=parent.frame(), substitute=FALSE, local=TRUE, gc=FALSE, earlySignal=FALSE, ...) {
+  if (substitute) expr <- substitute(expr)
+  args <- list(...)
+
+  core <- new.env(parent=emptyenv())
+  core$expr <- expr
+  core$envir <- envir
+  core$owner <- uuid()
+  core$local <- local
+  core$gc <- gc
+  core$earlySignal <- earlySignal
+
+  ## The current state of the future, e.g.
+  ## 'created', 'running', 'finished', 'failed', 'interrupted'.
+  core$state <- 'created'
+
+  ## Additional named arguments
+  for (key in names(args)) core[[key]] <- args[[key]]
+
+  structure(core, class=c("Future", class(core)))
+}
+
+
+#' @importFrom utils head
+#' @export
+print.Future <- function(x, ...) {
+  class <- class(x)
+  cat(sprintf("%s:\n", class[1]))
+  cat("Expression:\n")
+  print(x$expr)
+  cat(sprintf("Local evaluation: %s\n", x$local))
+  cat(sprintf("Environment: %s\n", capture.output(x$envir)))
+  g <- x$globals
+  ng <- length(g)
+  if (ng > 0) {
+    gSizes <- sapply(g, FUN=object.size)
+    gTotalSize <- sum(gSizes)
+    g <- head(g, n=5L)
+    gSizes <- head(gSizes, n=5L)
+    g <- sprintf("%s %s of %s", sapply(g, FUN=function(x) class(x)[1]), sQuote(names(g)), sapply(gSizes, FUN=asIEC))
+    if (ng > 5L) g <- sprintf("%s ...", g)
+    cat(sprintf("Globals: %d objects totaling %s (%s)\n", ng, asIEC(gTotalSize), g))
+  } else {
+    cat("Globals: <none>\n")
+  }
+
+  hasValue <- exists("value", envir=x, inherits=FALSE)
+
+  if (exists("value", envir=x, inherits=FALSE)) {
+    cat("Resolved: TRUE\n")
+  } else if (inherits(x, "LazyFuture")) {
+    ## FIXME: Special case; will there every be other cases
+    ## for which we need to support this? /HB 2016-05-03
+    cat("Resolved: FALSE\n")
+  } else {
+    ## resolved() without early signalling
+    ## FIXME: Make it easier to achieve this. /HB 2016-05-03
+    local({
+      earlySignal <- x$earlySignal
+      x$earlySignal <- FALSE
+      on.exit(x$earlySignal <- earlySignal)
+      cat(sprintf("Resolved: %s\n", resolved(x)))
+    })
+  }
+
+  if (hasValue) {
+    cat(sprintf("Value: %s of class %s\n", asIEC(object.size(x$value)), sQuote(class(x$value)[1])))
+  } else {
+    cat("Value: <not collected>\n")
+  }
+  cat(sprintf("Early signalling: %s\n", isTRUE(x$earlySignal)))
+  cat(sprintf("Owner process: %s\n", x$owner))
+  cat(sprintf("Class: %s\n", paste(sQuote(class), collapse=", ")))
+} ## print()
+
+
+## Checks whether Future is owned by the current process or not
+assertOwner <- function(future, ...) {
+  hpid <- function(uuid) {
+    info <- attr(uuid, "info")
+    sprintf("%s; pid %d on %s", uuid, info$pid, info$host)
+  }
+
+  if (!identical(future$owner, uuid())) {
+    stop(FutureError(sprintf("Invalid usage of futures: A future whose value has not yet been collected can only be queried by the R process (%s) that created it, not by any other R processes (%s): %s", hpid(future$owner), hpid(uuid()), hexpr(future$expr)), future=future))
+  }
+
+  invisible(future)
+}
+
+
+#' The value of a future
+#'
+#' Gets the value of a future.  If the future is unresolved, then
+#' the evaluation blocks until the future is resolved.
+#'
+#' @param future A \link{Future}.
+#' @param signal A logical specifying whether (\link[base]{conditions})
+#' should signaled or be returned as values.
+#' @param \dots Not used.
+#'
+#' @return An R object of any data type.
+#'
+#' @details
+#' This method needs to be implemented by the class that implement
+#' the Future API.
+#'
+#' @aliases value
+#' @rdname value
+#' @export
+#' @export value
+value.Future <- function(future, signal=TRUE, ...) {
+  if (!future$state %in% c('finished', 'failed', 'interrupted')) {
+    msg <- sprintf("Internal error: value() called on a non-finished future: %s", class(future)[1])
+    mdebug(msg)
+    stop(FutureError(msg, future=future))
+  }
+
+  value <- future$value
+  if (signal && future$state == 'failed') {
+    mdebug("Future state: %s", sQuote(value))
+    stop(FutureError(value, future=future))
+  }
+
+  value
+}
+
+value <- function(...) UseMethod("value")
+
+
+#' @export
+resolved.Future <- function(x, ...) {
+  ## Is future even launched?
+  if (x$state == 'created') return(FALSE)
+
+  ## Signal conditions early, iff specified for the given future
+  signalEarly(x, ...)
+
+  x$state %in% c('finished', 'failed', 'interrupted')
+}
+
+
+#' Inject code for the next type of future to use for nested futures
+#'
+#' @param future Current future.
+#' @param ... Not used.
+#'
+#' @return A future expression with code injected to set what
+#' type of future to use for nested futures, iff any.
+#'
+#' @details
+#' If no next future strategy is specified, the default is to
+#' use \link{eager} futures.  This conservative approach protects
+#' against spawning off recursive futures by mistake, especially
+#' \link{multicore} and \link{multisession} ones.
+#' The default will also set \code{options(mc.cores=0L)}, which
+#' means that no \emph{additional} R processes may be spawned off
+#' by functions such as \code{\link[parallel:mclapply]{mclapply}()}
+#' and friends (*).
+#'
+#' Currently it is not possible to specify what type of nested
+#' futures to be used, meaning the above default will always be
+#' used.
+#' See \href{https://github.com/HenrikBengtsson/future/issues/37}{Issue #37}
+#' for plans on adding support for custom nested future types.
+#'
+#' (*) Note that using \code{mc.cores=0} will unfortunately cause
+#'     \code{mclapply()} and friends to generate an error saying
+#'     "'mc.cores' must be >= 1".  Ideally those functions should
+#'     fall back to using the non-multicore alternative in this
+#'     case, e.g. \code{mclapply(...)} => \code{lapply(...)}.
+#'     See \url{https://github.com/HenrikBengtsson/Wishlist-for-R/issues/7}
+#'     for a discussion on this.
+#'
+#' @export
+#' @aliases getExpression.Future
+#' @keywords internal
+getExpression <- function(future, ...) UseMethod("getExpression")
+
+#' @export
+getExpression.Future <- function(future, mc.cores=NULL, ...) {
+  strategies <- plan("list")
+
+  ## If end of future stack, fall back to using single-core
+  ## processing.  In this case we don't have to rely
+  ## on the future package.  Instead, we can use the
+  ## light-weight approach where we force the number of
+  ## cores available to be one.  This we achieve by
+  ## setting the number of _additional_ cores to be
+  ## zero (sic!).
+  if (length(strategies) == 0) {
+    mc.cores <- 0L
+  }
+
+  ## Should 'mc.cores' be set?
+  if (!is.null(mc.cores)) {
+    ## FIXME: How can we guarantee that '...future.mc.cores.old'
+    ## is not overwritten?  /HB 2016-03-14
+    enter <- bquote({
+      ## covr: skip=2
+      ...future.mc.cores.old <- getOption("mc.cores")
+      options(mc.cores=.(mc.cores))
+    })
+
+    exit <- bquote({
+      ## covr: skip=1
+      options(mc.cores=...future.mc.cores.old)
+    })
+  } else {
+    enter <- exit <- NULL
+  }
+
+  if (length(strategies) > 0) {
+    exit <- bquote({
+      ## covr: skip=2
+      .(exit)
+      future::plan(.(strategies))
+    })
+  }
+
+  ## Identify package namespaces for strategies
+  pkgs <- lapply(strategies, FUN=environment)
+  pkgs <- lapply(pkgs, FUN=environmentName)
+  pkgs <- unique(unlist(pkgs))
+  pkgs <- intersect(pkgs, loadedNamespaces())
+  mdebug("Packages to be loaded by expression (n=%d): %s", length(pkgs), paste(sQuote(pkgs), collapse=", "))
+  
+  if (length(pkgs) > 0L) {
+    ## Sanity check by verifying packages can be loaded already here
+    ## If there is somethings wrong in 'pkgs', we get the error
+    ## already before launching the future.
+    for (pkg in pkgs) loadNamespace(pkg)
+
+    enter <- bquote({
+      ## covr: skip=3
+      .(enter)      
+      ## TROUBLESHOOTING: If the package fails to load, then library()
+      ## suppress that error and generates a generic much less
+      ## informative error message.  Because of this, we load the
+      ## namespace first (to get a better error message) and then
+      ## calls library(), which attaches the package. /HB 2016-06-16
+      for (pkg in .(pkgs)) {
+        loadNamespace(pkg)
+        library(pkg, character.only=TRUE)
+      }
+      oplans <- future::plan("list")
+    })
+  } else {
+    enter <- bquote({
+      ## covr: skip=2
+      .(enter)
+      oplans <- future::plan("list")
+    })
+  }
+
+  if (length(strategies) >= 2L) {
+    enter <- bquote({
+      ## covr: skip=2
+      .(enter)
+      future::plan(.(strategies[-1]))
+    })
+  }
+
+  makeExpression(expr=future$expr, local=future$local, gc=future$gc, enter=enter, exit=exit)
+} ## getExpression()
+
+
+makeExpression <- function(expr, local=TRUE, gc=FALSE, globals.onMissing=getOption("future.globals.onMissing", "error"), enter=NULL, exit=NULL) {
+  ## Evaluate expression in a local() environment?
+  if (local) {
+    a <- NULL; rm(list="a")  ## To please R CMD check
+    expr <- substitute(local(a), list(a=expr))
+  }
+
+  ## Set and reset certain future.* options
+  enter <- substitute({
+    ## covr: skip=7
+    ...future.oldOptions <- options(
+      ## Prevent .future.R from being source():d when future is attached
+      future.startup.loadScript=FALSE,
+      ## Assert globals when future is created (or at run time)?
+      future.globals.onMissing=globals.onMissing
+    )
+    enter
+  }, env=list(globals.onMissing=globals.onMissing, enter=enter))
+
+  exit <- substitute({
+    exit
+    options(...future.oldOptions)
+  }, env=list(exit=exit))
+
+
+  ## NOTE: We don't want to use local(body) w/ on.exit() because
+  ## evaluation in a local is optional, cf. argument 'local'.
+  ## If this was mandatory, we could.  Instead we use
+  ## a tryCatch() statement. /HB 2016-03-14
+  if (gc) {
+    expr <- substitute({
+      ## covr: skip=8
+      enter
+      ...future.value <- tryCatch({
+        body
+      }, finally = {
+        exit
+      })
+      gc(verbose=FALSE, reset=FALSE)
+      ...future.value
+    }, env=list(enter=enter, body=expr, exit=exit, cleanup=cleanup))
+  } else {
+    expr <- substitute({
+      ## covr: skip=6
+      enter
+      tryCatch({
+        body
+      }, finally = {
+        exit
+      })
+    }, env=list(enter=enter, body=expr, exit=exit))
+  }
+
+  expr
+} ## makeExpression()
diff --git a/R/FutureError-class.R b/R/FutureError-class.R
new file mode 100644
index 0000000..6d3e856
--- /dev/null
+++ b/R/FutureError-class.R
@@ -0,0 +1,91 @@
+#' An error occurred while trying to evaluate a future
+#'
+#' @param message The error message.
+#' @param call The call stack that led up to the error.
+#' @param future The \link{Future} involved.
+#' @param output Output captured when error occurred.
+#'
+#' @return An \link[base:conditions]{error} object of class FutureError.
+#'
+#' @aliases getOutput
+#' @export
+#' @keywords internal
+FutureError <- function(message, call=NULL, future=NULL, output=NULL) {
+  if (inherits(message, "error")) {
+    ex <- message
+  } else {
+    ex <- simpleError(message, call=call)
+  }
+  ex$future <- future
+  ex$output <- output
+  class(ex) <- unique(c("FutureError", class(ex)))
+  ex
+}
+
+
+#' @export
+print.FutureError <- function(x, ...) {
+  NextMethod("print")
+
+  future <- x$future
+  output <- x$output
+  if (!is.null(future) || !is.null(output)) {
+    cat("\n\nDEBUG: BEGIN TROUBLESHOOING HELP\n")
+
+    if (!is.null(future)) {
+      cat("Future involved:\n")
+      print(future)
+      cat("\n")
+    }
+
+    cond <- future$value
+    if (inherits(cond, "condition")) {
+      fcalls <- cond$traceback
+      if (!is.null(fcalls)) {
+        cat("Future call stack:\n")
+        print(fcalls)
+        cat("\n")
+      }
+    }
+
+    if (!is.null(output)) {
+      cat("Captured output:\n")
+      cat(getOutput(x, tail=30L, collapse="\n"))
+      cat("\n\n")
+    }
+
+    cat("DEBUG: END TROUBLESHOOING HELP\n")
+  }
+
+  invisible(x)
+} ## print()
+
+
+#' @export
+getOutput.FutureError <- function(x, collapse=NULL, head=NULL, tail=NULL, ...) {
+  output <- x$output
+
+  ## Return "as is"?
+  if (is.null(collapse) && is.null(head) && is.null(tail)) return(output)
+
+  ## Truncate?
+  if (!is.null(head) && !is.null(tail)) {
+    idxs <- seq_along(output)
+    idxs <- sort(unique(c(head(idxs, n=head), tail(idxs, n=tail))))
+    output <- output[idxs]
+    idxs
+  } else if (!is.null(head)) {
+    output <- head(output, n=head)
+  } else if (!is.null(tail)) {
+    output <- tail(output, n=tail)
+  }
+
+  ## Collapse? (add line endings)
+  if (!is.null(collapse)) output <- paste(output, collapse=collapse)
+
+  output
+} ## getOutput()
+
+
+#' @export
+getOutput <- function(...) UseMethod("getOutput")
diff --git a/R/FutureRegistry.R b/R/FutureRegistry.R
new file mode 100644
index 0000000..d598109
--- /dev/null
+++ b/R/FutureRegistry.R
@@ -0,0 +1,100 @@
+FutureRegistry <- local({
+  db <- list()
+
+  indexOf <- function(futures, future) {
+    for (ii in seq_along(futures)) {
+      if (identical(future, futures[[ii]])) return(ii)
+    }
+    NA_integer_
+  }
+
+  collectValues <- function(where, futures, firstOnly=TRUE) {
+    for (ii in seq_along(futures)) {
+      future <- futures[[ii]]
+
+      ## Is future even launched?
+      if (future$state == "created") next
+
+      ## NOTE: It is when calling resolved() on a future with
+      ##       early signaling is enabled that conditioned
+      ##       may be signaled.
+      if (resolved(future)) {
+        ## (a) Let future cleanup after itself, iff needed.
+        ##     This, this may result in a call to
+        ##     FutureRegistry(..., action="remove").
+        value(future, signal=FALSE)
+
+        ## (b) Make sure future is removed from registry, unless
+        ##     already done via above value() call.
+        futuresDB <- db[[where]]
+        idx <- indexOf(futuresDB, future=future)
+        if (!is.na(idx)) {
+          futuresDB[[idx]] <- NULL
+          db[[where]] <<- futuresDB
+        }
+
+        ## (c) Collect only the first resolved future?
+        if (firstOnly) break
+      }
+    } ## for (ii ...)
+
+    invisible(futures)
+  } ## collectValues()
+
+
+  function(where, action=c("add", "remove", "list", "collect-first", "reset"), future=NULL, earlySignal=TRUE, ...) {
+    stopifnot(length(where) == 1, nzchar(where))
+    futures <- db[[where]]
+
+    ## Automatically create?
+    if (is.null(futures)) {
+      futures <- list()
+      db[[where]] <<- futures
+    }
+
+    if (action == "add") {
+      idx <- indexOf(futures, future=future)
+      if (!is.na(idx)) {
+        msg <- sprintf("Cannot add to %s registry. %s is already registered.", sQuote(where), class(future)[1])
+        mdebug("ERROR: %s", msg)
+        stop(msg)
+      }
+      futures[[length(futures)+1L]] <- future
+      db[[where]] <<- futures
+    } else if (action == "remove") {
+      idx <- indexOf(futures, future=future)
+      if (is.na(idx)) {
+        msg <- sprintf("Cannot remove from %s registry. %s not registered.", sQuote(where), class(future)[1])
+        mdebug("ERROR: %s", msg)
+        stop(msg)
+      }
+      futures[[idx]] <- NULL
+      db[[where]] <<- futures
+    } else if (action == "collect-first") {
+      collectValues(where, futures=futures, firstOnly=TRUE)
+    } else if (action == "reset") {
+      db[[where]] <<- list()
+    } else if (action == "list") {
+    } else {
+      msg <- sprintf("INTERNAL ERROR: Unknown action to %s registry: %s", sQuote(where), action)
+      mdebug(msg)
+      stop(msg)
+    }
+
+    ## Early signaling of conditions?
+    if (earlySignal && length(futures) > 0L) {
+      ## Which futures have early signaling enabled?
+      idxs <- lapply(futures, FUN=function(f) f$earlySignal)
+      idxs <- which(unlist(idxs, use.names=FALSE))
+
+      ## Any futures to be scanned for early signaling?
+      if (length(idxs) > 0) {
+        ## Collect values, which will trigger signaling during
+        ## calls to resolved().
+        collectValues(where, futures=futures[idxs], firstOnly=FALSE)
+      }
+    }
+
+    futures
+  }
+})
diff --git a/R/LazyFuture-class.R b/R/LazyFuture-class.R
new file mode 100644
index 0000000..5bd7280
--- /dev/null
+++ b/R/LazyFuture-class.R
@@ -0,0 +1,50 @@
+#' A lazy future is a future whose value will be resolved at the time when it is requested
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE).
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param local If TRUE, the expression is evaluated such that
+#' all assignments are done to local temporary environment, otherwise
+#' the assignments are done in the calling environment.
+#' @param gc If TRUE, the garbage collector run after the future is resolved.
+#' @param \dots Additional named elements of the future.
+#'
+#' @return An object of class \code{LazyFuture}.
+#'
+#' @seealso
+#' To evaluate an expression using "lazy future", see function
+#' \code{\link{lazy}()}.
+#'
+#' @export
+#' @name LazyFuture-class
+#' @keywords internal
+LazyFuture <- function(expr=NULL, envir=parent.frame(), substitute=FALSE, local=TRUE, gc=FALSE, ...) {
+  if (substitute) expr <- substitute(expr)
+  f <- UniprocessFuture(expr=expr, envir=envir, substitute=FALSE, local=local, gc=gc, ...)
+  structure(f, class=c("LazyFuture", class(f)))
+}
+
+#' @export
+resolved.LazyFuture <- function(x, ...) {
+  ## resolved() for LazyFuture must force value() such that
+  ## the future gets resolved.  The reason for this is so
+  ## that polling is always possible, e.g.
+  ## while(!resolved(f)) Sys.sleep(5);
+  value(x, signal=FALSE)
+  NextMethod("resolved")
+}
+
+#' @export
+value.LazyFuture <- function(future, signal=TRUE, ...) {
+  future <- evaluate(future)
+
+  value <- future$value
+  if (signal && future$state == 'failed') {
+    mdebug("Future state: %s", sQuote(value))
+    stop(FutureError(value, future=future))
+  }
+
+  value
+}
diff --git a/R/MulticoreFuture-class.R b/R/MulticoreFuture-class.R
new file mode 100644
index 0000000..8ba5211
--- /dev/null
+++ b/R/MulticoreFuture-class.R
@@ -0,0 +1,132 @@
+#' An multicore future is a future whose value will be resolved asynchroneously in a parallel process
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE).
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param \dots Additional named elements of the future.
+#'
+#' @return An object of class \code{MulticoreFuture}.
+#'
+#' @seealso
+#' To evaluate an expression using "multicore future", see function
+#' \code{\link{multicore}()}.
+#'
+#' @export
+#' @name MulticoreFuture-class
+#' @keywords internal
+MulticoreFuture <- function(expr=NULL, envir=parent.frame(), substitute=FALSE, ...) {
+  if (substitute) expr <- substitute(expr)
+
+  f <- MultiprocessFuture(expr=expr, envir=envir, substitute=FALSE, job=NULL, ...)
+  structure(f, class=c("MulticoreFuture", class(f)))
+}
+
+
+run <- function(...) UseMethod("run")
+
+run.MulticoreFuture <- function(future, ...) {
+  ## Assert that the process that created the future is
+  ## also the one that evaluates/resolves/queries it.
+  assertOwner(future)
+
+  mcparallel <- importParallel("mcparallel")
+
+  expr <- getExpression(future)
+  envir <- future$envir
+
+  requestCore(
+    await=function() FutureRegistry("multicore", action="collect-first"),
+    workers=future$workers
+  )
+
+  ## Add to registry
+  FutureRegistry("multicore", action="add", future=future)
+
+  future.args <- list(expr)
+  job <- do.call(parallel::mcparallel, args=future.args, envir=envir)
+
+  future$job <- job
+  future$state <- 'running'
+
+  invisible(future)
+}
+
+#' @export
+resolved.MulticoreFuture <- function(x, timeout=0.2, ...) {
+  ## Is future even launched?
+  if (x$state == 'created') return(FALSE)
+
+  ## Is value already collected?
+  if (x$state %in% c('finished', 'failed', 'interrupted')) return(TRUE)
+
+  ## Assert that the process that created the future is
+  ## also the one that evaluates/resolves/queries it.
+  assertOwner(x)
+
+  selectChildren <- importParallel("selectChildren")
+  job <- x$job
+  stopifnot(inherits(job, "parallelJob"))
+
+  ## NOTE: We cannot use mcollect(job, wait=FALSE, timeout=0.2),
+  ## because that will return NULL if there's a timeout, which is
+  ## an ambigous value because the future expression may return NULL.
+  ## WORKAROUND: Adopted from parallel::mccollect().
+  pid <- selectChildren(job, timeout=timeout)
+  res <- (is.integer(pid) || is.null(pid))
+
+  ## Signal conditions early? (happens only iff requested)
+  if (res) signalEarly(x, ...)
+
+  res
+}
+
+#' @export
+value.MulticoreFuture <- function(future, signal=TRUE, ...) {
+  ## Has the value already been collected?
+  if (future$state %in% c('finished', 'failed', 'interrupted')) {
+    return(NextMethod("value"))
+  }
+
+  ## Assert that the process that created the future is
+  ## also the one that evaluates/resolves/queries it.
+  assertOwner(future)
+
+  ## If not, wait for process to finish, and
+  ## then collect and record the value
+  mccollect <- importParallel("mccollect")
+  job <- future$job
+  stopifnot(inherits(job, "parallelJob"))
+  res <- mccollect(job, wait=TRUE)[[1L]]
+
+  ## SPECIAL: Check for fallback 'fatal error in wrapper code'
+  ## try-error from parallel:::mcparallel().  If detected, then
+  ## turn into an error with a more informative error message, cf.
+  ## https://github.com/HenrikBengtsson/future/issues/35
+  if (identical(res, structure("fatal error in wrapper code", class="try-error"))) {
+    stop(FutureError(sprintf("Detected an error ('%s') by the 'parallel' package while trying to retrieve the value of a %s (%s). This could be because the forked R process that evalutes the future was terminated before it was completed.", res, class(future)[1], sQuote(hexpr(future$expr))), future=future))
+  }
+
+  ## Update value and state
+  condition <- attr(res, "condition")
+  if (inherits(condition, "simpleError")) {
+    future$state <- 'failed'
+    future$value <- condition
+  } else {
+    future$value <- res
+    future$state <- 'finished'
+  }
+  res <- NULL ## Not needed anymore
+
+  ## Remove from registry
+  FutureRegistry("multicore", action="remove", future=future)
+
+  NextMethod("value")
+}
+
+
+#' @export
+getExpression.MulticoreFuture <- function(future, mc.cores=0L, ...) {
+  NextMethod("getExpression", mc.cores=mc.cores)
+}
diff --git a/R/MultiprocessFuture-class.R b/R/MultiprocessFuture-class.R
new file mode 100644
index 0000000..1bd4856
--- /dev/null
+++ b/R/MultiprocessFuture-class.R
@@ -0,0 +1,24 @@
+#' An multiprocess future is a future whose value will be resolved asynchroneously in a parallel process
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE).
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param \dots Additional named elements of the future.
+#'
+#' @return An object of class \code{MultiprocessFuture}.
+#'
+#' @seealso
+#' To evaluate an expression using "multiprocess future", see function
+#' \code{\link{multiprocess}()}.
+#'
+#' @export
+#' @name MultiprocessFuture-class
+#' @keywords internal
+MultiprocessFuture <- function(expr=NULL, envir=parent.frame(), substitute=FALSE, ...) {
+  if (substitute) expr <- substitute(expr)
+
+  f <- Future(expr=expr, envir=envir, substitute=FALSE, ...)
+  structure(f, class=c("MultiprocessFuture", class(f)))
+}
diff --git a/R/MultisessionFuture-class.R b/R/MultisessionFuture-class.R
new file mode 100644
index 0000000..f5751cf
--- /dev/null
+++ b/R/MultisessionFuture-class.R
@@ -0,0 +1,13 @@
+## Currently aliased in ClusterFuture
+#' @export
+MultisessionFuture <- function(expr=NULL, envir=parent.frame(), substitute=FALSE, local=!persistent, persistent=FALSE, workers=NULL, ...) {
+  if (substitute) expr <- substitute(expr)
+  f <- ClusterFuture(expr=expr, envir=envir, substitute=FALSE, local=local, persistent=persistent, workers=workers, ...)
+  structure(f, class=c("MultisessionFuture", class(f)))
+}
+
+
+#' @export
+getExpression.MultisessionFuture <- function(future, mc.cores=0L, ...) {
+  NextMethod("getExpression", mc.cores=mc.cores)
+}
diff --git a/R/UniprocessFuture-class.R b/R/UniprocessFuture-class.R
new file mode 100644
index 0000000..ffcb227
--- /dev/null
+++ b/R/UniprocessFuture-class.R
@@ -0,0 +1,74 @@
+#' An uniprocess future is a future whose value will be resolved synchroneously in the current process
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE).
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param local If TRUE, the expression is evaluated such that
+#' all assignments are done to local temporary environment, otherwise
+#' the assignments are done in the calling environment.
+#' @param \dots Additional named elements of the future.
+#'
+#' @return An object of class \code{UniprocessFuture}.
+#'
+#' @seealso
+#' To evaluate an expression using "uniprocess future", see functions
+#' \code{\link{eager}()} and \code{\link{lazy}()}.
+#'
+#' @export
+#' @name UniprocessFuture-class
+#' @keywords internal
+UniprocessFuture <- function(expr=NULL, envir=parent.frame(), substitute=FALSE, local=TRUE, ...) {
+  if (substitute) expr <- substitute(expr)
+  f <- Future(expr=expr, envir=envir, substitute=FALSE, local=local, ...)
+  structure(f, class=c("UniprocessFuture", class(f)))
+}
+
+
+evaluate <- function(...) UseMethod("evaluate")
+
+evaluate.UniprocessFuture <- function(future, ...) {
+  if (future$state %in% c('finished', 'failed', 'interrupted')) {
+    return(invisible(future))
+  }
+
+  ## Assert that the process that created the future is
+  ## also the one that evaluates/resolves/queries it.
+  assertOwner(future)
+
+  expr <- getExpression(future)
+  envir <- future$envir
+
+  ## Run future
+  future$state <- 'running'
+
+
+  ## WORKAROUND: tryCatch() does not record the traceback and
+  ## it is too late to infer it when the error has been caught.
+  ## Because of this with we use withCallingHandlers() to
+  ## capture errors and if they occur we record the call trace.
+  current <- sys.nframe()
+  tryCatch({
+    withCallingHandlers({
+      future$value <- eval(expr, envir=envir)
+      future$state <- 'finished'
+    }, error = function(ex) {
+      calls <- sys.calls()
+      ## Drop fluff added by withCallingHandlers()
+      calls <- calls[seq_len(length(calls)-2L)]
+      ## Drop fluff added by outer tryCatch()
+      calls <- calls[-seq_len(current+7L)]
+      ## Drop fluff added by outer local=TRUE
+      if (future$local) calls <- calls[-seq_len(6L)]
+      ex$traceback <- calls
+      future$value <- ex
+      future$state <- 'failed'
+    })
+  }, error = function(ex) {})
+
+  ## Signal conditions early, iff specified for the given future
+  signalEarly(future, collect=FALSE)
+
+  invisible(future)
+}
diff --git a/R/availableCores.R b/R/availableCores.R
new file mode 100644
index 0000000..53d34ac
--- /dev/null
+++ b/R/availableCores.R
@@ -0,0 +1,187 @@
+#' Get number of available cores on current machine
+#'
+#' The current/main R session counts as one, meaning the minimum
+#' number of cores available is always at least one.
+#'
+#' @param constraints An optional character specifying under what
+#' constraints ("purposes") we are requesting the values.
+#' For instance, on systems where multicore processing is not supported
+#' (i.e. Windows), using \code{constrains="multicore"} will force a
+#' single core to be reported.
+#' @param methods A character vector specifying how to infer the number
+#' of available cores.
+#' @param na.rm If TRUE, only non-missing settings are considered/returned.
+#' @param default The default number of cores to return if no non-missing
+#' settings are available.
+#' @param which A character specifying which settings to return.
+#' If \code{"min"}, the minimum value is returned.
+#' If \code{"max"}, the maximum value is returned (be careful!)
+#' If \code{"all"}, all values are returned.
+#'
+#' @return Return a positive (>=1) integer.
+#' If \code{which="all"}, then more than one value may be returned.
+#' Together with \code{na.rm=FALSE} missing values may also be returned.
+#'
+#' @details
+#' The following settings ("methods") for inferring the number of cores
+#' are supported:
+#' \itemize{
+#'  \item \code{"system"} -
+#'    Query \code{\link[parallel]{detectCores}()}.
+#'  \item \code{"mc.cores+1"} -
+#'    If available, returns the value of option
+#'    \code{\link[base:options]{mc.cores}} + 1.
+#'    Note that \option{mc.cores} is defined as the number of
+#'    \emph{additional} R processes that can be used in addition to the
+#'    main R process.  This means that with \code{mc.cores=0} all
+#'    calculations should be done in the main R process, i.e. we have
+#'    exactly one core available for our calculations.
+#'    The \option{mc.cores} option defaults to environment variable
+#'    \env{MC_CORES} (and is set accordingly when the \pkg{parallel}
+#'    package is loaded).  The \option{mc.cores} option is used by for
+#'    instance \code{\link[parallel]{mclapply}()}.
+#'  \item \code{"PBS"} -
+#'    Query Torque/PBS environment variable \env{PBS_NUM_PPN}.
+#'    Depending on PBS system configuration, this \emph{resource} parameter
+#'    may or may not default to one.  It can be specified when submitting
+#'    a job as in, for instance, \code{qsub -l nodes=4:ppn=2}, which
+#'    requests four nodes each with two cores.
+#'  \item \code{"SGE"} -
+#'    Query Sun/Oracle Grid Engine (SGE) environment variable
+#'    \env{NSLOTS}.
+#'    It can be specified when submitting a job as in, for instance,
+#'    \code{qsub -pe by_node 2}, which two cores on a single machine.
+#'  \item \code{"Slurm"} -
+#'    Query Simple Linux Utility for Resource Management (Slurm)
+#'    environment variable \env{SLURM_CPUS_PER_TASK}.
+#'    This may or may not be set.  It can be set when submitting a job,
+#'    e.g. \code{sbatch --cpus-per-task=2 hello.sh} or by adding
+#'    \code{#SBATCH --cpus-per-task=2} to the `hello.sh` script.
+#' }
+#' For any other value of a \code{methods} element, the R option with the
+#' same name is queried.  If that is not set, the system environment
+#' variable is queried.  If neither is set, a missing value is returned.
+#'
+#'
+#' @export
+#' @keywords internal
+availableCores <- function(constraints=NULL, methods=getOption("future.availableCores.methods", c("system", "mc.cores+1", "_R_CHECK_LIMIT_CORES_", "Slurm", "PBS", "SGE")), na.rm=TRUE, default=c(current=1L), which=c("min", "max", "all")) {
+  ## Local functions
+  getenv <- function(name) {
+    as.integer(trim(Sys.getenv(name, NA_character_)))
+  } # getenv()
+
+  getopt <- function(name) {
+    as.integer(getOption(name, NA_integer_))
+  } # getopt()
+
+  which <- match.arg(which)
+  stopifnot(length(default) == 1, is.finite(default), default >= 1L)
+
+  ncores <- rep(NA_integer_, times=length(methods))
+  names(ncores) <- methods
+  for (kk in seq_along(methods)) {
+    method <- methods[kk]
+    if (method == "Slurm") {
+      ## Number of cores assigned by Slurm
+      n <- getenv("SLURM_CPUS_PER_TASK")
+    } else if (method == "PBS") {
+      ## Number of cores assigned by Torque/PBS
+      n <- getenv("PBS_NUM_PPN")
+    } else if (method == "SGE") {
+      ## Number of cores assigned by Sun/Oracle Grid Engine (SGE)
+      n <- getenv("NSLOTS")
+    } else if (method == "mc.cores") {
+      n <- getopt("mc.cores") + 1L
+      .Deprecated(msg="Method 'mc.cores' for future::availableCores() is deprecated; use 'mc.cores+1' instead.")
+    } else if (method == "mc.cores+1") {
+      ## Number of cores by option defined by 'parallel' package
+      n <- getopt("mc.cores") + 1L
+    } else if (method == "_R_CHECK_LIMIT_CORES_") {
+      ## A flag set by R CMD check for constraining number of
+      ## cores allowed to be use in package tests.  Here we
+      ## acknowledge this and sets number of cores to the
+      ## maximum two allowed.  This way we don't have to explicitly
+      ## use options(mc.cores=2L) in example code, which may be
+      ## misleading to the reader.
+      chk <- tolower(Sys.getenv("_R_CHECK_LIMIT_CORES_", ""))
+      chk <- (nzchar(chk) && (chk != "false"))
+      if (chk) n <- 3L ## = 2+1
+    } else if (method == "system") {
+      ## Number of cores available according to parallel::detectCores()
+      n <- detectCores()
+    } else {
+      ## covr: skip=3
+      ## Fall back to querying option and system environment variable
+      ## with the given name
+      n <- getopt(method)
+      if (is.na(n)) n <- getenv(method)
+    }
+    ncores[kk] <- n
+  }
+
+  ## Validate settings
+  ncoresT <- ncores[!is.na(ncores)]
+  ncoresT <- ncoresT[ncoresT <= 0]
+  if (length(ncoresT) > 0) {
+    msg <- sprintf("Detected invalid (zero or less) core settings: %s",
+         paste(paste0(sQuote(names(ncoresT)), "=", ncoresT), collapse=", "))
+    mdebug(msg)
+    stop(msg)
+  }
+
+  ## Drop missing values?
+  if (na.rm) {
+    ncores <- ncores[!is.na(ncores)]
+  }
+
+  ## Fall back to the default?
+  if (length(ncores) == 0) ncores <- default
+
+  if (which == "min") {
+    ## which.min() to preserve name
+    ncores <- ncores[which.min(ncores)]
+  } else if (which == "max") {
+    ## which.max() to preserve name
+    ncores <- ncores[which.max(ncores)]
+  }
+
+  if (!is.null(constraints)) {
+    if (constraints == "multicore") {
+      ## SPECIAL: On some supports such as Windows, multicore processing
+      ## is not supported.  If so, we should override all values to
+      ## to reflect that only a single core is available
+      if (!supportsMulticore()) ncores[] <- 1L
+    }
+  }
+
+  ## Sanity check
+  stopifnot(all(ncores >= 1L, na.rm=TRUE))
+
+  ncores
+} # availableCores()
+
+
+#' Check whether multicore processing is supported or not
+#'
+#' Multicore futures are only supported on systems supporting
+#' multicore processing.  R supports this on most systems,
+#' except on Microsoft Windows.
+#'
+#' @return TRUE if multicore processing is supported, otherwise FALSE.
+#'
+#' @seealso
+#' To use multicore futures, use \code{\link{plan}(\link{multicore})}.
+#'
+#' @export
+supportsMulticore <- local({
+  supported <- NA
+  function() {
+    if (is.na(supported)) {
+      ns <- getNamespace("parallel")
+      supported <<- exists("mcparallel", mode="function", envir=ns, inherits=FALSE)
+    }
+    supported
+  }
+})
+
diff --git a/R/backtrace.R b/R/backtrace.R
new file mode 100644
index 0000000..b8feec9
--- /dev/null
+++ b/R/backtrace.R
@@ -0,0 +1,35 @@
+#' Back trace the expressions evaluated before a condition was caught
+#'
+#' @param future The future with a caught condition.
+#' @param envir the environment where to locate the future.
+#' @param \dots Not used.
+#'
+#' @return A list of calls.
+#'
+#' @export
+backtrace <- function(future, envir=parent.frame(), ...) {
+  ## Argument 'expr':
+  expr <- substitute(future)
+
+  if (!is.null(expr)) {
+    target <- parse_env_subset(expr, envir=envir, substitute=FALSE)
+    future <- get_future(target, mustExist=TRUE)
+  }
+
+  if (!resolved(future)) {
+    stop("No condition has been caught because the future is unresolved: ", sQuote(expr))
+  }
+
+  value <- future$value
+  if (!inherits(value, "condition")) {
+    stop("No condition was caught for this future: ", sQuote(expr))
+  }
+
+  calls <- value$traceback
+  if (is.null(calls)) {
+    stop("No call trace was recorded for this future: ", sQuote(expr))
+  }
+
+  calls
+} ## backtrace()
+
diff --git a/R/cluster.R b/R/cluster.R
new file mode 100644
index 0000000..b173c8b
--- /dev/null
+++ b/R/cluster.R
@@ -0,0 +1,50 @@
+#' Create a cluster future whose value will be resolved asynchroneously in a parallel process
+#'
+#' A cluster future is a future that uses cluster evaluation,
+#' which means that its \emph{value is computed and resolved in
+#' parallel in another process}.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done and from which globals are obtained.
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param persistent If FALSE, the evaluation environment is cleared
+#' from objects prior to the evaluation of the future.
+#' @param workers A cluster object created by
+#' \code{\link[parallel]{makeCluster}()}.
+#' @param earlySignal Specified whether conditions should be signaled as soon as possible or not.
+#' @param \dots Not used.
+#'
+#' @return A \link{ClusterFuture}.
+#'
+#' @example incl/cluster.R
+#'
+#' @details
+#' This function will block if all available R cluster nodes are
+#' occupied and will be unblocked as soon as one of the already
+#' running cluster futures is resolved.
+#'
+#' The preferred way to create an cluster future is not to call
+#' this function directly, but to register it via
+#' \code{\link{plan}(cluster)} such that it becomes the default
+#' mechanism for all futures.  After this \code{\link{future}()}
+#' and \code{\link{\%<=\%}} will create \emph{cluster futures}.
+#'
+#' @export
+cluster <- function(expr, envir=parent.frame(), substitute=TRUE, persistent=FALSE, workers=NULL, gc=FALSE, earlySignal=FALSE, ...) {
+  ## BACKWARD COMPATIBILITY
+  args <- list(...)
+  if ("cluster" %in% names(args)) {
+    workers <- args$cluster
+    .Deprecated(msg="Argument 'cluster' has been renamed to 'workers'. Please update your script/code that uses the future package.")
+  }
+
+  if (substitute) expr <- substitute(expr)
+
+  future <- ClusterFuture(expr=expr, envir=envir, substitute=FALSE, persistent=persistent, workers=workers, gc=gc, earlySignal=earlySignal, ...)
+  run(future)
+}
+class(cluster) <- c("cluster", "multiprocess", "future", "function")
diff --git a/R/constant.R b/R/constant.R
new file mode 100644
index 0000000..cd52553
--- /dev/null
+++ b/R/constant.R
@@ -0,0 +1,6 @@
+## Used only internally
+constant <- function(value, ...) {
+  future <- ConstantFuture(value=value, ...)
+  evaluate(future)
+}
+class(constant) <- c("constant", "uniprocess", "future", "function")
diff --git a/R/eager.R b/R/eager.R
new file mode 100644
index 0000000..160d770
--- /dev/null
+++ b/R/eager.R
@@ -0,0 +1,69 @@
+#' Create an eager future whose value will be resolved immediately
+#'
+#' An eager future is a future that uses eager evaluation, which means
+#' that its \emph{value is computed and resolved immediately}, which is
+#' how regular expressions are evaluated in R.
+#' The only difference to R itself is that globals are validated
+#' by default just as for all other types of futures in this package.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE).
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param globals If TRUE, global objects are validated at the point
+#' in time when the future is created (always before it is resolved),
+#' that is, they identified and located.  If some globals fail to be
+#' located, an informative error is generated.
+#' @param local If TRUE, the expression is evaluated such that
+#' all assignments are done to local temporary environment, otherwise
+#' the assignments are done in the calling environment.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param earlySignal Specified whether conditions should be signaled as soon as possible or not.
+#' @param \dots Not used.
+#'
+#' @return An \link{EagerFuture}.
+#'
+#' @example incl/eager.R
+#'
+#' @details
+#' The preferred way to create an eager future is not to call this function
+#' directly, but to register it via \code{\link{plan}(eager)} such that it
+#' becomes the default mechanism for all futures.  After this
+#' \code{\link{future}()} and \code{\link{\%<=\%}} will create
+#' \emph{eager futures}.
+#'
+#' @section transparent futures:
+#' Transparent futures are eager futures configured to emulate how R
+#' evaluates expressions as far as possible.  For instance, errors and
+#' warnings are signaled immediately and assignments are done to the
+#' calling environment (without \code{local()} as default for all other
+#' types of futures).  This makes transparent futures ideal for
+#' troubleshooting, especially when there are errors.
+#'
+#' @aliases transparent
+#' @export transparent
+#' @export
+eager <- function(expr, envir=parent.frame(), substitute=TRUE, globals=TRUE, local=TRUE, gc=FALSE, earlySignal=FALSE, ...) {
+  if (substitute) expr <- substitute(expr)
+  globals <- as.logical(globals)
+  local <- as.logical(local)
+
+  ## Validate globals at this point in time?
+  if (globals) {
+    exportGlobals(expr, envir=envir, target=NULL, tweak=tweakExpression, resolve=TRUE)
+  }
+
+  future <- EagerFuture(expr=expr, envir=envir, substitute=FALSE, local=local, gc=gc, earlySignal=earlySignal)
+  evaluate(future)
+}
+class(eager) <- c("eager", "uniprocess", "future", "function")
+
+
+transparent <- function(expr, envir=parent.frame(), substitute=TRUE, globals=FALSE, local=FALSE, gc=FALSE, earlySignal=TRUE, ...) {
+  if (substitute) expr <- substitute(expr)
+  future <- eager(expr, envir=envir, substitute=FALSE, globals=globals, local=local, gc=gc, earlySignal=earlySignal)
+  invisible(future)
+}
+class(transparent) <- c("transparent", "eager", "uniprocess", "future", "function")
diff --git a/R/flapply.R b/R/flapply.R
new file mode 100644
index 0000000..c13bdf8
--- /dev/null
+++ b/R/flapply.R
@@ -0,0 +1,23 @@
+## FIXME: Do we need an envir argument here?
+#' @importFrom listenv listenv
+fleapply <- function(x, FUN, ...) {
+  stopifnot(is.function(FUN))
+  res <- listenv()
+  for (ii in seq_along(x)) {
+    x_ii <- x[[ii]]
+    res[[ii]] <- future(FUN(x_ii, ...))
+  }
+  names(res) <- names(x)
+
+  ## Not needed anymore
+  rm(list=c("x", "FUN", "ii"))
+
+  ## Resolve and return as values
+  values(res)
+} # fleapply()
+
+
+## FIXME: Do we need an envir argument here?
+flapply <- function(x, FUN, ...) {
+  as.list(fleapply(x=x, FUN=FUN, ...))
+}
diff --git a/R/future.R b/R/future.R
new file mode 100644
index 0000000..52fe564
--- /dev/null
+++ b/R/future.R
@@ -0,0 +1,50 @@
+#' Create a future
+#'
+#' Creates a future from an expression and returns it.
+#' The state of the future is either unresolved or resolved.
+#' When it becomes resolved, at some point in the future,
+#' its value can be retrieved.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} from where global
+#' objects should be identified.  Depending on "evaluator",
+#' it may also be the environment in which the expression
+#' is evaluated.
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param evaluator The actual function that evaluates
+#' \code{expr} and returns a future.  The evaluator function
+#' should accept all the same arguments as this function
+#' (except \code{evaluator}).
+#' @param \dots Additional arguments passed to the "evaluator".
+#'
+#' @return A \link{Future}.
+#'
+#' @example incl/future.R
+#'
+#' @seealso
+#' It is recommended that the evaluator is \emph{non-blocking}
+#' (returns immediately), but it is not required.
+#
+#' The default evaluator function is \code{\link{eager}()},
+#' but this can be changed via \code{\link{plan}()} function.
+#'
+#' @aliases futureCall
+#' @export
+#' @name future
+future <- function(expr, envir=parent.frame(), substitute=TRUE, evaluator=plan(), ...) {
+  if (substitute) expr <- substitute(expr)
+
+  if (!is.function(evaluator)) {
+    stop("Argument 'evaluator' must be a function: ", typeof(evaluator))
+  }
+
+  future <- evaluator(expr, envir=envir, substitute=FALSE, ...)
+
+  ## Assert that a future was returned
+  if (!inherits(future, "Future")) {
+    stop("Argument 'evaluator' specifies a function that does not return a Future object: ", paste(sQuote(class(future)), collapse=", "))
+  }
+
+  future
+}
diff --git a/R/futureAssign.R b/R/futureAssign.R
new file mode 100644
index 0000000..06997f6
--- /dev/null
+++ b/R/futureAssign.R
@@ -0,0 +1,84 @@
+#' Create a future and assign its value to a variable as a promise
+#'
+#' Method and infix operators for creating futures and assigning
+#' their values as variables using \link[base]{promise}s.  Trying
+#' to access such a "future variable" will correspond to requesting
+#' the value of the underlying future.  If the the future is already
+#' resolved at this time, then the value will be available
+#' instantaneously and the future variable will appear as any other
+#' variable.  If the future is unresolved, then the current process
+#' will block until the future is resolved and the value is available.
+#'
+#' @param name the name of the variable (and the future) to assign.
+#' @param value the expression to be evaluated in the future and
+#' whose value will be assigned to the variable.
+#' @param envir The environment from which global variables used by
+#' the expression should be search for.
+#' @param assign.env The environment to which the variable should
+#' be assigned.
+#' @param substitute Controls whether \code{expr} should be
+#' \code{substitute()}:d or not.
+#'
+#' @return A \link{Future} invisibly.
+#'
+#' @example incl/futureAssign_OP.R
+#'
+#' @details
+#' This function creates a future and a corresponding
+#' \emph{\link[base]{promise}}, which hold the future's value.
+#' Both the future and the promise are assigned to environment
+#' \code{assign.env}.  The name of the promise is given by \code{name}
+#' and the name of the future is \code{.future_<name>}.
+#' The future is also returned invisibly.
+#'
+#' @seealso
+#' The \code{\link{futureOf}()} function can be used to get the
+#' Future object of a future variable.
+#'
+#' @aliases %<-% %->% %<=% %=>%
+#' @export
+#' @export %<-% %->% %<=% %=>%
+futureAssign <- function(name, value, envir=parent.frame(), assign.env=envir, substitute=TRUE) {
+  stopifnot(is.character(name), !is.na(name), nzchar(name))
+  if (substitute) value <- substitute(value)
+
+  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  ## (1) Create future
+  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  ## Name of "future" saved in parallel with the "promise"
+  future_name <- sprintf(".future_%s", name)
+  if (exists(future_name, envir=envir)) {
+    msg <- sprintf("A future with name %s already exists in environment %s: %s", sQuote(future_name), sQuote(environmentName(envir)), hpaste(ls(envir=envir, all.names=TRUE)))
+##    warning(msg)
+  }
+
+  ## Evaluate expression/value as a "future" and assign its value to
+  ## a variable as a "promise".
+  ## NOTE: We make sure to pass 'envir' in order for globals to
+  ## be located properly.
+  future.args <- list(value, envir=envir)
+  future <- do.call(future::future, args=future.args, envir=assign.env)
+
+  ## Assign future to assignment environment
+  future_without_gc <- future
+  future_without_gc$.gcenv <- NULL
+  assign(future_name, future_without_gc, envir=assign.env)
+
+
+  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  ## (2) Create promise holding the future's value
+  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  ## Here value may throw an error causing the assign value to be a
+  ## "delayed" error, which will be thrown each time the variable is
+  ## retrieved.
+  env <- new.env()
+  env$job <- future
+  delayedAssign(name, local({
+    value <- value(future)
+    ## Remove internal future variable
+    rm(list=future_name, envir=assign.env)
+    value
+  }), eval.env=env, assign.env=assign.env)
+
+  invisible(future)
+}
diff --git a/R/futureAssign_OP.R b/R/futureAssign_OP.R
new file mode 100644
index 0000000..2014d00
--- /dev/null
+++ b/R/futureAssign_OP.R
@@ -0,0 +1,39 @@
+#' @importFrom listenv get_variable parse_env_subset
+futureAssignInternal <- function(target, expr, envir=parent.frame(), substitute=FALSE) {
+  target <- parse_env_subset(target, envir=envir, substitute=substitute)
+  assign.env <- target$envir
+
+  name <- target$name
+  if (inherits(target$envir, "listenv")) {
+    if (target$exists) {
+      name <- get_variable(target$envir, target$idx, mustExist=TRUE, create=FALSE)
+    } else {
+      if (!is.na(name) && nzchar(name)) {
+        name <- get_variable(target$envir, name, mustExist=FALSE, create=TRUE)
+      } else if (all(is.finite(target$idx))) {
+        name <- get_variable(target$envir, target$idx, mustExist=FALSE, create=TRUE)
+      } else {
+        msg <- "INTERNAL ERROR: Zero length variable name and unknown index."
+        mdebug(msg)
+        stop(msg)
+      }
+    }
+  }
+
+  futureAssign(name, expr, envir=envir, assign.env=assign.env, substitute=FALSE)
+} # futureAssignInternal()
+
+
+`%<-%` <- `%<=%` <- function(x, value) {
+  target <- substitute(x)
+  expr <- substitute(value)
+  envir <- parent.frame(1)
+  futureAssignInternal(target, expr, envir=envir, substitute=FALSE)
+}
+
+`%->%` <- `%=>%` <- function(value, x) {
+  target <- substitute(x)
+  expr <- substitute(value)
+  envir <- parent.frame(1)
+  futureAssignInternal(target, expr, envir=envir, substitute=FALSE)
+}
diff --git a/R/futureCall.R b/R/futureCall.R
new file mode 100644
index 0000000..b15f151
--- /dev/null
+++ b/R/futureCall.R
@@ -0,0 +1,16 @@
+#' @param FUN A function object.
+#' @param args A list of arguments passed to function \code{FUN}.
+#'
+#' @rdname future
+#'
+#' @export
+futureCall <- function(FUN, args=NULL, envir=parent.frame(), evaluator=plan(), ...) {
+  stopifnot(is.function(FUN))
+  stopifnot(is.list(args))
+
+  envirT <- new.env(parent=envir)
+  envirT$FUN <- FUN
+  envirT$args <- args
+
+  future(do.call(what=FUN, args=args), substitute=TRUE, envir=envirT, evaluator=evaluator)
+} # futureCall()
diff --git a/R/futureOf.R b/R/futureOf.R
new file mode 100644
index 0000000..35cb07a
--- /dev/null
+++ b/R/futureOf.R
@@ -0,0 +1,121 @@
+#' Get the future of a future variable
+#'
+#' Get the future of a future variable that has been created directly
+#' or indirectly via \code{\link{future}()}.
+#'
+#' @param var the variable.  If NULL, all futures in the
+#' environment are returned.
+#' @param envir the environment where to search from.
+#' @param mustExist If TRUE and the variable does not exists, then
+#' an informative error is thrown, otherwise NA is returned.
+#' @param default the default value if future was not found.
+#' @param drop if TRUE and \code{var} is NULL, then returned list
+#' only contains futures, otherwise also \code{default} values.
+#'
+#' @return A \link{Future} (or \code{default}).
+#' If \code{var} is NULL, then a named list of Future:s are returned.
+#'
+#' @example incl/futureOf.R
+#'
+#' @export
+#' @importFrom listenv map parse_env_subset
+futureOf <- function(var=NULL, envir=parent.frame(), mustExist=TRUE, default=NA, drop=FALSE) {
+  ## Argument 'expr':
+  expr <- substitute(var)
+
+
+  ## Inspect by expression?
+  if (!is.null(expr)) {
+    target <- parse_env_subset(expr, envir=envir, substitute=FALSE)
+    future <- get_future(target, mustExist=mustExist)
+    return(future)
+  }
+
+
+  ## Otherwise, inspect all variables in environment
+  if (inherits(envir, "listenv")) {
+    map <- map(envir)
+    res <- list()
+    length(res) <- length(map)
+    names(res) <- names(map)
+
+    for (idx in seq_along(res)) {
+      target <- parse_env_subset(idx, envir=envir, substitute=FALSE)
+      future <- get_future(target, mustExist=FALSE, default=default)
+      if (!is.null(future) || !is.atomic(future) || !is.na(future)) {
+        res[[idx]] <- future
+      }
+    }
+  } else {
+    ## names(x) is only supported in R (>= 3.2.0)
+    vars <- ls(envir=envir, all.names=TRUE)
+    vars <- grep("^.future_", vars, invert=TRUE, value=TRUE)
+    res <- lapply(vars, FUN=function(var) {
+      target <- parse_env_subset(var, envir=envir, substitute=FALSE)
+      get_future(target, mustExist=FALSE, default=default)
+    })
+    names(res) <- vars
+  }
+
+  ## Keep only futures?
+  if (drop && length(res) > 0) {
+    keep <- sapply(res, FUN=inherits, "Future")
+    res <- res[keep]
+  } else {
+    ## Preserve dimensions
+    dim <- dim(envir)
+    if (!is.null(dim)) {
+      dim(res) <- dim
+      dimnames(res) <- dimnames(envir)
+    }
+  }
+
+  res
+}
+
+
+get_future <- function(target, mustExist=TRUE, default=NA) {
+  res <- default
+
+  if (!target$exists) {
+    msg <- sprintf("No such future variable: %s", target$code)
+    if (mustExist) {
+      mdebug("ERROR: %s", msg)
+      stop(msg, call.=FALSE)
+    }
+    attr(res, "reason") <- msg
+    return(res)
+  }
+
+  envir <- target$envir
+  envirName <- environmentName(envir)
+  if (!nzchar(envirName)) envirName <- "<noname>"
+
+  ## (a) Check if element is a future promise
+  if (inherits(envir, "listenv")) {
+    map <- map(envir)
+    name <- map[target$idx]
+  } else {
+    name <- target$name
+  }
+  future_name <- sprintf(".future_%s", name)
+  if (exists(future_name, envir=envir, inherits=FALSE)) {
+    return(get(future_name, envir=envir, inherits=FALSE))
+  }
+
+  ## (b) Check if element itself is a future object
+  if (exists(name, envir=envir, inherits=FALSE)) {
+    future <- get(name, envir=envir, inherits=FALSE)
+    if (inherits(future, "Future")) return(future)
+  }
+
+  ## Not found
+  msg <- sprintf("Future (%s) not found in %s %s: %s", sQuote(name), class(envir)[1], sQuote(envirName), sQuote(target$code))
+  if (mustExist) {
+    mdebug("ERROR: %s", msg)
+    stop(msg, call.=FALSE)
+  }
+
+  attr(res, "reason") <- msg
+  res
+} # get_future()
diff --git a/R/futures.R b/R/futures.R
new file mode 100644
index 0000000..a2b3e15
--- /dev/null
+++ b/R/futures.R
@@ -0,0 +1,76 @@
+#' Gets all futures in an object
+#'
+#' Gets all futures in an environment, a list, or a list environment
+#' and returns an object of the same class (and dimensions).
+#' Non-future elements are returned as is.
+#'
+#' @param x An environment, a list, or a list environment.
+#' @param ... Not used.
+#'
+#' @return An object of same type as \code{x} and with the same names
+#' and/or dimensions, if set.
+#'
+#' @details
+#' This function is useful for retrieve futures that were created via
+#' future assignments (\code{\%<=\%}) and therefore stored as promises.
+#' This function turns such promises into standard \code{Future}
+#' objects.
+#'
+#' @export
+futures <- function(x, ...) UseMethod("futures")
+
+#' @export
+futures.list <- function(x, ...) {
+  x
+}
+
+#' @export
+futures.environment <- function(x, ...) {
+  fs <- futureOf(envir=x, mustExist=FALSE, drop=FALSE)
+
+  ## Create object of same class as 'x'
+  res <- new.env()
+  for (key in names(fs)) {
+    f <- fs[[key]]
+    if (inherits(f, "Future")) {
+      res[[key]] <- f
+    } else {
+      res[[key]] <- x[[key]]
+    }
+  }
+
+  res
+}
+
+#' @export
+#' @importFrom listenv listenv
+futures.listenv <- function(x, ...) {
+  fs <- futureOf(envir=x, mustExist=FALSE, drop=FALSE)
+
+  ## Create object of same class as 'x'
+  res <- listenv()
+  length(res) <- length(fs)
+  for (ii in seq_along(fs)) {
+    f <- fs[[ii]]
+    if (inherits(f, "Future")) {
+      res[[ii]] <- f
+    } else {
+      value <- x[[ii]]
+      if (is.null(value)) {
+        res[ii] <- list(value)
+      } else {
+        res[[ii]] <- value
+      }
+    }
+  }
+
+  dim <- dim(x)
+  if (!is.null(dim)) {
+    dim(res) <- dim
+    ## Preserve dimnames and names
+    dimnames(res) <- dimnames(x)
+  }
+  names(res) <- names(x)
+
+  res
+}
diff --git a/R/globals.R b/R/globals.R
new file mode 100644
index 0000000..078c604
--- /dev/null
+++ b/R/globals.R
@@ -0,0 +1,200 @@
+#' @importFrom globals globalsOf packagesOf cleanup
+#' @importFrom utils packageVersion
+exportGlobals <- function(expr, envir, target=envir, tweak=NULL, resolve=getOption("future.globals.resolve", FALSE), persistent=FALSE) {
+  gp <- getGlobalsAndPackages(expr, envir=envir, tweak=tweak, resolve=resolve, persistent=persistent)
+  globals <- gp$globals
+
+  ## Inject global objects?
+  if (!is.null(target)) {
+    for (name in names(globals)) {
+      target[[name]] <- globals[[name]]
+    }
+  }
+
+  invisible(globals)
+} # exportGlobals()
+
+
+
+#' @importFrom globals globalsOf packagesOf cleanup
+#' @importFrom utils object.size
+getGlobalsAndPackages <- function(expr, envir=parent.frame(), tweak=tweakExpression, resolve=getOption("future.globals.resolve", FALSE), persistent=FALSE, ...) {
+  ## Local functions
+  attachedPackages <- function() {
+    pkgs <- search()
+    pkgs <- grep("^package:", pkgs, value=TRUE)
+    pkgs <- gsub("^package:", "", pkgs)
+    pkgs
+  }
+
+  asPkgEnvironment <- function(pkg) {
+    name <- sprintf("package:%s", pkg)
+    if (!name %in% search()) return(emptyenv())
+    as.environment(name)
+  } ## asPkgEnvironment()
+
+
+  ## Maximum size of globals (to prevent too large exports) = 500 MiB
+  maxSizeOfGlobals <- getOption("future.globals.maxSize", 500*1024^2)
+  maxSizeOfGlobals <- as.numeric(maxSizeOfGlobals)
+  stopifnot(!is.na(maxSizeOfGlobals), maxSizeOfGlobals > 0)
+
+  ## Assert that all identified globals exists when future is created?
+  if (persistent) {
+    ## If future relies on persistent storage, then the globals may
+    ## already exist in the environment that the future is evaluated in.
+    mustExist <- FALSE
+  } else {
+    ## Default for 'future.globals.onMissing':
+    ## Note: It's possible to switch between 'ignore' and 'error'
+    ##       at any time. Tests handles both cases. /HB 2016-06-18
+    globals.onMissing <- getOption("future.globals.onMissing", "ignore")
+    globals.onMissing <- match.arg(globals.onMissing, choices=c("error", "ignore"))
+    mustExist <- is.element(globals.onMissing, "error")
+  }
+
+
+  ## Identify globals
+  ## Algorithm for identifying globals
+  globals.method <- getOption("future.globals.method", "ordered")
+  globals <- globalsOf(expr, envir=envir, substitute=FALSE,
+               tweak=tweak,
+               dotdotdot="return",
+               primitive=FALSE, base=FALSE,
+               unlist=TRUE,
+               mustExist=mustExist,
+               method=globals.method
+             )
+
+  exprOrg <- expr
+
+  ## Tweak expression to be called with global ... arguments?
+  if (inherits(globals$`...`, "DotDotDotList")) {
+    ## Missing global '...'?
+    if (!is.list(globals$`...`)) {
+      msg <- sprintf("Did you mean to create the future within a function?  Invalid future expression tries to use global '...' variables that do not exist: %s", hexpr(exprOrg))
+      mdebug(msg)
+      stop(msg)
+    }
+
+    globals$`future.call.arguments` <- globals$`...`
+    globals$`...` <- NULL
+
+    ## To please R CMD check
+    a <- `future.call.arguments` <- NULL
+    rm(list=c("a", "future.call.arguments"))
+    expr <- substitute({
+      ## covr: skip=1
+      do.call(function(...) a, args=`future.call.arguments`)
+    }, list(a=expr))
+  }
+
+  ## Resolve futures and turn into already-resolved "constant" futures
+  ## We restrict ourselves to this here in order to avoid having to
+  ## recursively try to resolve everything in every global which may
+  ## or may not point to packages (include base R package)
+  if (resolve && length(globals) > 0L) {
+    mdebug("Resolving globals that are futures ...")
+    idxs <- which(unlist(lapply(globals, FUN=inherits, "Future")))
+    mdebug("Number of global futures: %d", length(idxs))
+    if (length(idxs) > 0) {
+      mdebug("Global futures: %s", hpaste(sQuote(names(globals[idxs]))))
+      valuesF <- values(globals[idxs])
+      globals[idxs] <- lapply(valuesF, FUN=ConstantFuture)
+      valuesF <- NULL  ## Not needed anymore
+    }
+    idxs <- NULL ## Not needed anymore
+    mdebug("Resolving global that are futures ... DONE")
+  }
+
+
+  pkgs <- NULL
+  if (length(globals) > 0L) {
+    ## Append packages associated with globals
+    pkgs <- packagesOf(globals)
+
+    ## Drop all globals which are located in one of
+    ## the packages in 'pkgs'.  They will be available
+    ## since those packages are attached.
+    where <- attr(globals, "where")
+
+    names <- names(globals)
+    keep <- rep(TRUE, times=length(globals))
+    names(keep) <- names
+    for (name in names) {
+      pkg <- environmentName(where[[name]])
+      pkg <- gsub("^package:", "", pkg)
+      if (pkg %in% pkgs) {
+        ## Only drop exported objects
+        if (exists(name, envir=asPkgEnvironment(pkg)))
+          keep[name] <- FALSE
+      }
+    }
+    if (!all(keep)) globals <- globals[keep]
+
+    ## Now drop globals that are primitive functions or
+    ## that are part of the base packages, which now are
+    ## part of 'pkgs' if needed.
+    globals <- cleanup(globals)
+  }
+
+
+  ## Resolve all remaing globals
+  ## FIXME: Should we resolve package names spaces too? Should
+  ## We assume they can contain futures?  We do it for now, but
+  ## if this turns out to be too expensive, maybe we should
+  ## only dive into such environments if they have a certain flag
+  ## set.  /HB 2016-02-04
+  if (resolve && length(globals) > 0L) {
+    mdebug("Resolving futures part of globals (recursively) ...")
+    globals <- resolve(globals, value=TRUE, recursive=TRUE)
+    mdebug("Resolving futures part of globals (recursively) ... DONE")
+  }
+
+
+  ## Protect against user error exporting too large objects?
+  if (length(globals) > 0L && is.finite(maxSizeOfGlobals)) {
+    sizes <- lapply(globals, FUN=object.size)
+    sizes <- unlist(sizes, use.names=TRUE)
+    totalExportSize <- sum(sizes, na.rm=TRUE)
+    if (totalExportSize > maxSizeOfGlobals) {
+      n <- length(sizes)
+      o <- order(sizes, decreasing=TRUE)[1:3]
+      o <- o[is.finite(o)]
+      sizes <- sizes[o]
+      classes <- lapply(globals[o], FUN=mode)
+      classes <- unlist(classes, use.names=FALSE)
+      largest <- sprintf("%s (%s of class %s)", sQuote(names(sizes)), asIEC(sizes), sQuote(classes))
+      msg <- sprintf("The total size of all global objects that need to be exported for the future expression (%s) is %s. This exceeds the maximum allowed size of %s (option 'future.global.maxSize').", sQuote(hexpr(exprOrg)), asIEC(totalExportSize), asIEC(maxSizeOfGlobals))
+      if (n == 1) {
+        fmt <- "%s There is one global: %s."
+      } else if (n == 2) {
+        fmt <- "%s There are two globals: %s."
+      } else if (n == 3) {
+        fmt <- "%s There are three globals: %s."
+      } else {
+        fmt <- "%s The three largest globals are %s."
+      }
+      msg <- sprintf(fmt, msg, hpaste(largest, lastCollapse=" and "))
+      mdebug(msg)
+      stop(msg)
+    }
+  }
+
+
+  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  ## Any packages to export?
+  ## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  ## Never attach the 'base' package, because that is always
+  ## available for all R sessions / implementations.
+  pkgs <- setdiff(pkgs, "base")
+  if (length(pkgs) > 0L) {
+    ## Record which packages in 'pkgs' that are loaded and
+    ## which of them are attached (at this point in time).
+    isLoaded <- is.element(pkgs, loadedNamespaces())
+    isAttached <- is.element(pkgs, attachedPackages())
+    pkgs <- pkgs[isAttached]
+  }
+
+  list(expr=expr, globals=globals, packages=pkgs)
+} ## getGlobalsAndPackages()
diff --git a/R/lazy.R b/R/lazy.R
new file mode 100644
index 0000000..bdd88dc
--- /dev/null
+++ b/R/lazy.R
@@ -0,0 +1,65 @@
+#' Create a lazy future whose value will be resolved at the time when requested
+#'
+#' A lazy future is a future that uses lazy evaluation, which means
+#' that its \emph{value is only computed and resolved at the time when the
+#' value is requested}.  This means that the future will not be resolved
+#' if the value is never requested.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done (or inherits from if \code{local} is TRUE)
+#' and from which globals are obtained.
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param local If TRUE, the expression is evaluated such that
+#' all assignments are done to local temporary environment, otherwise
+#' the assignments are done in the calling environment.
+#' @param globals If TRUE, global objects are resolved ("frozen") at
+#' the point of time when the future is created, otherwise they are
+#' resolved when the future is resolved.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param earlySignal Specified whether conditions should be signaled as soon as possible or not.
+#' @param \dots Not used.
+#'
+#' @return A \link{LazyFuture}.
+#'
+#' @example incl/lazy.R
+#'
+#' @details
+#' The preferred way to create a lazy future is not to call this function
+#' directly, but to register it via \code{\link{plan}(lazy)} such that it
+#' becomes the default mechanism for all futures.  After this
+#' \code{\link{future}()} and \code{\link{\%<=\%}} will create
+#' \emph{lazy futures}.
+#'
+#' @export
+lazy <- function(expr, envir=parent.frame(), substitute=TRUE, globals=TRUE, local=TRUE, gc=FALSE, earlySignal=FALSE, ...) {
+  if (substitute) expr <- substitute(expr)
+  globals <- as.logical(globals)
+  local <- as.logical(local)
+  if (!local && globals) {
+    stop("Non-supported call to lazy(): Argument 'globals' must be FALSE whenever 'local' is FALSE. Lazy future evaluation in the calling environment (local=FALSE) can only be done if global objects are resolved at the same time (globals=FALSE).")
+  }
+
+
+  ## Evaluate in "local" environment?
+  if (local || globals) {
+    envir <- new.env(parent=envir)
+  }
+
+
+  ## Resolve globals at this point in time?
+  if (globals) {
+    exportGlobals(expr, envir=envir, target=envir, tweak=tweakExpression, resolve=TRUE)
+  }
+
+  LazyFuture(expr=expr, envir=envir, local=local, globals=globals, gc=gc, earlySignal=earlySignal)
+}
+class(lazy) <- c("lazy", "uniprocess", "future", "function")
+
+## WORKAROUND:
+## Avoid lazyeval::print.lazy() being called with print(lazy())
+## https://github.com/HenrikBengtsson/future/issues/52
+class(lazy) <- c("function", class(lazy))
+
diff --git a/R/mandelbrot.R b/R/mandelbrot.R
new file mode 100644
index 0000000..0d423b2
--- /dev/null
+++ b/R/mandelbrot.R
@@ -0,0 +1,188 @@
+#' Mandelbrot convergence counts
+#'
+#' @param Z               A complex matrix for which convergence
+#'                        counts should be calculated.
+#' @param xmid,ymid,side,resolution Alternative specification of
+#'                        the complex plane \code{Z}, where
+#'                        \code{mean(Re(Z)) == xmid},
+#'                        \code{mean(Im(Z)) == ymid},
+#'                        \code{diff(range(Re(Z))) == side},
+#'                        \code{diff(range(Im(Z))) == side}, and
+#'                        \code{dim(Z) == c(resolution, resolution)}.
+#' @param maxIter         Maximum number of iterations per bin.
+#' @param tau             A threshold; the radius when calling
+#'                        divergence (Mod(z) > tau).
+#'
+#' @return Returns an integer matrix (of class Mandelbrot) with
+#' non-negative counts.
+#'
+#' @examples
+#' counts <- mandelbrot(xmid=-0.75, ymid=0, side=3)
+#' str(counts)
+#' \dontrun{
+#' plot(counts)
+#' }
+#' 
+#' \dontrun{
+#' demo("mandelbrot", package="future", ask=FALSE)
+#' }
+#'
+#' @author The internal Mandelbrot algorithm was inspired by and
+#' adopted from similar GPL code of Martin Maechler (available
+#' from ftp://stat.ethz.ch/U/maechler/R/ on 2005-02-18 [sic!]).
+#'
+#' @aliases as.raster.Mandelbrot plot.Mandelbrot mandelbrotTiles
+#' @export
+#'
+#' @keywords internal
+mandelbrot <- function(...) UseMethod("mandelbrot")
+
+#' @export
+mandelbrot.matrix <- function(Z, maxIter=200L, tau=2.0, ...) {
+  stopifnot(is.matrix(Z), mode(Z) == "complex")
+  
+  ## By default, assume none of the elements will converge
+  counts <- matrix(maxIter, nrow=nrow(Z), ncol=ncol(Z))
+
+  ## But as a start, flag the to all be non-diverged
+  nonDiverged <- rep(TRUE, times=length(Z))
+  idxOfNonDiverged <- seq_along(nonDiverged)
+
+  ## SPEEDUP: The Mandelbrot sequence will only be calculated on the
+  ## "remaining set" of complex numbers that yet hasn't diverged.
+  sZ <- Z ## The Mandelbrot sequence of the "remaining" set
+  Zr <- Z ## The original complex number of the "remaining" set
+
+  for (ii in seq_len(maxIter-1L)) {
+    sZ <- sZ*sZ + Zr
+
+    ## Did any of the "remaining" points diverge?
+    diverged <- (Mod(sZ) > tau)
+    if (any(diverged)) {
+      ## Record at what iteration divergence occurred
+      counts[idxOfNonDiverged[diverged]] <- ii
+
+      ## Early stopping?
+      keep <- which(!diverged)
+      if (length(keep) == 0) break
+
+      ## Drop from remain calculations
+      idxOfNonDiverged <- idxOfNonDiverged[keep]
+      nonDiverged[nonDiverged] <- !diverged
+
+      ## Update the "remaining" set of complex numbers
+      sZ <- sZ[keep]
+      Zr <- Zr[keep]
+    }
+  }
+
+  attr(counts, "params") <- list(Z=Z, maxIter=maxIter, tau=tau)
+
+  class(counts) <- c("Mandelbrot", class(counts))
+  
+  counts
+} ## mandelbrot() for matrix
+
+
+#' @export
+mandelbrot.numeric <- function(xmid=-0.75, ymid=0, side=3, resolution=400L, maxIter=200L, tau=2, ...) {
+  ## Validate arguments
+  stopifnot(side > 0) 
+  resolution <- as.integer(resolution)
+  stopifnot(resolution > 0)
+
+  maxIter <- as.integer(maxIter)
+  stopifnot(maxIter > 0)
+
+  ## The nx-by-ny bins
+  nx <- ny <- resolution
+
+  ## Setup (x,y) bins
+  xrange <- xmid + c(-1,1)*side/2
+  yrange <- ymid + c(-1,1)*side/2
+  x <- seq(from=xrange[1], to=xrange[2], length.out=nx)
+  y <- seq(from=yrange[1], to=yrange[2], length.out=ny)
+
+  ## Set of complex numbers to be investigated
+  Z <- outer(y, x, FUN=function(y,x) complex(real=x, imaginary=y))
+
+  mandelbrot(Z, maxIter=maxIter, tau=tau)
+} ## mandelbrot() for numeric
+
+
+#' @export
+#' @importFrom grDevices as.raster hsv
+#' @keywords internal
+as.raster.Mandelbrot <- function(x, ...) {
+  maxIter <- attr(x, "params")$maxIter
+  img <- hsv(h=x/maxIter, s=1, v=1)
+  img[x == maxIter] <- "#000000"
+  dim(img) <- dim(x)
+  img <- t(img)
+  img <- structure(img, class="raster")
+  img
+} ## as.raster()
+
+
+#' @export
+#' @importFrom grDevices as.raster
+#' @importFrom graphics par plot
+#' @keywords internal
+plot.Mandelbrot <- function(x, y, ..., mar=c(0,0,0,0)) {
+  if (!is.null(mar)) {
+    opar <- par(mar=c(0,0,0,0))
+    on.exit(par(opar))
+  }
+  plot(as.raster(x), ...)
+}
+
+
+#' @export
+mandelbrotTiles <- function(xmid=-0.75, ymid=0.0, side=3.0, nrow=2L, ncol=nrow, resolution=400L, truncate=TRUE) {
+  ## Validate arguments
+  stopifnot(side > 0) 
+  resolution <- as.integer(resolution)
+  stopifnot(resolution > 0)
+
+  ## The nx-by-ny bins
+  nx <- ny <- resolution
+
+  ## Bins per tile
+  dx <- ceiling(nx / ncol)
+  dy <- ceiling(ny / nrow)
+  stopifnot(dx > 0, dy > 0)
+
+  ## Truncate so all tiles have identical dimensions?
+  if (truncate) {
+    nx <- ncol * dx
+    ny <- nrow * dy 
+  }
+  
+  ## Setup (x,y) bins
+  xrange <- xmid + c(-1,1)*side/2
+  yrange <- ymid + c(-1,1)*side/2
+  x <- seq(from=xrange[1], to=xrange[2], length.out=nx)
+  y <- seq(from=yrange[1], to=yrange[2], length.out=ny)
+
+
+  ## Generate tiles row by row
+  res <- list()
+  for (rr in seq_len(nrow)) {
+    yrr <- if (rr < nrow) y[1:dy] else y
+    y <- y[-(1:dy)]
+      
+    xrr <- x
+    for (cc in seq_len(ncol)) {
+      xcc <- if (cc < ncol) xrr[1:dx] else xrr
+      xrr <- xrr[-(1:dx)]
+    
+      Ccc <- outer(yrr, xcc, FUN=function(y,x) complex(real=x, imaginary=y))
+      attr(Ccc, "region") <- list(xrange=range(xcc), yrange=range(yrr))
+      attr(Ccc, "tile") <- c(rr, cc)
+      res <- c(res, list(Ccc))
+    }
+  }
+  dim(res) <- c(nrow, ncol)
+  
+  res
+} ## mandelbrotTiles()
diff --git a/R/multicore.R b/R/multicore.R
new file mode 100644
index 0000000..ebff9aa
--- /dev/null
+++ b/R/multicore.R
@@ -0,0 +1,206 @@
+#' Create a multicore future whose value will be resolved asynchroneously in a forked parallel process
+#'
+#' A multicore future is a future that uses multicore evaluation,
+#' which means that its \emph{value is computed and resolved in
+#' parallel in another process}.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done and from which globals are obtained.
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param globals If TRUE, global objects are validated at the point
+#' in time when the future is created (always before it is resolved),
+#' that is, they identified and located.  If some globals fail to be
+#' located, an informative error is generated.
+#' @param workers The maximum number of multicore futures that can
+#' be active at the same time before blocking.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param earlySignal Specified whether conditions should be signaled as soon as possible or not.
+#' @param \dots Not used.
+#'
+#' @return A \link{MulticoreFuture}
+#' If \code{workers == 1}, then all processing using done in the
+#' current/main R session and we therefore fall back to using
+#' a eager future.  This is also the case whenever multicore
+#' processing is not supported, e.g. on Windows.
+#'
+#' @example incl/multicore.R
+#'
+#' @details
+#' This function will block if all cores are occupied and
+#' will be unblocked as soon as one of the already running
+#' multicore futures is resolved.  For the total number of
+#' cores available including the current/main R process, see
+#' \code{\link{availableCores}()}.
+#'
+#' Not all systems support multicore futures.  For instance,
+#' it is not supported on Microsoft Windows.  Trying to create
+#' multicore futures on non-supported systems will silently
+#' fall back to using \link{eager} futures, which effectively
+#' corresponds to a multicore future that can handle one parallel
+#' process (the current one) before blocking.
+#'
+#' The preferred way to create an multicore future is not to call
+#' this function directly, but to register it via
+#' \code{\link{plan}(multicore)} such that it becomes the default
+#' mechanism for all futures.  After this \code{\link{future}()}
+#' and \code{\link{\%<=\%}} will create \emph{multicore futures}.
+#'
+#' @seealso
+#' For processing in multiple background R sessions, see
+#' \link{multisession} futures.
+#' For multicore processing with fallback to multisession where
+#' the former is not supported, see \link{multiprocess} futures.
+#'
+#' Use \code{\link{availableCores}()} to see the total number of
+#' cores that are available for the current R session.
+#' Use \code{\link{availableCores}("multicore") > 1L} to check
+#' whether multicore futures are supported or not on the current
+#' system.
+#'
+#' @export
+multicore <- function(expr, envir=parent.frame(), substitute=TRUE, globals=TRUE, workers=availableCores(constraints="multicore"), gc=FALSE, earlySignal=FALSE, ...) {
+  ## BACKWARD COMPATIBILITY
+  args <- list(...)
+  if ("maxCores" %in% names(args)) {
+    workers <- args$maxCores
+    .Deprecated(msg="Argument 'maxCores' has been renamed to 'workers'. Please update you script/code that uses the future package.")
+  }
+
+  if (substitute) expr <- substitute(expr)
+  globals <- as.logical(globals)
+  workers <- as.integer(workers)
+  stopifnot(is.finite(workers), workers >= 1L)
+
+  ## Fall back to eager futures if only a single additional R process
+  ## can be spawned off, i.e. then use the current main R process.
+  ## Eager futures best reflect how multicore futures handle globals.
+  if (workers == 1L || !supportsMulticore()) {
+    ## covr: skip=1
+    return(eager(expr, envir=envir, substitute=FALSE, globals=globals, local=TRUE, gc=gc))
+  }
+
+  ## Validate globals at this point in time?
+  if (globals) {
+    exportGlobals(expr, envir=envir, target=NULL, tweak=tweakExpression, resolve=TRUE)
+  }
+
+  oopts <- options(mc.cores=workers)
+  on.exit(options(oopts))
+
+  future <- MulticoreFuture(expr=expr, envir=envir, substitute=FALSE, workers=workers, gc=gc, earlySignal=earlySignal)
+  run(future)
+}
+class(multicore) <- c("multicore", "multiprocess", "future", "function")
+
+
+
+#' Get number of cores currently used
+#'
+#' Get number of children plus one (for the current process)
+#' used by the current R session.  The number of children
+#' is the total number of subprocesses launched by this
+#' process that are still running and whose values have yet
+#' not been collected.
+#'
+#' @return A positive integer equal or greater than one.
+#'
+#' @keywords internal
+usedCores <- function() {
+  ## Number of unresolved multicore futures
+  futures <- FutureRegistry("multicore", action="list")
+  nfutures <- length(futures)
+  ncores <- nfutures
+
+  ## Total number of multicore processes
+  ## To please R CMD check
+  ns <- getNamespace("parallel")
+  children <- get("children", envir=ns, mode="function")
+  nchildren <- length(children())
+
+  ## Any multicore processes that are not futures?
+  if (nchildren > nfutures) {
+    ## The basic assumption is that any additional multicore
+    ## processes have been launched by at least one of the
+    ## multicore futures.  This means that as long as we
+    ## wait for one of these futures to be resolved, then
+    ## a CPU core will always be available at some point in
+    ## the future.
+    ## covr: skip=7
+    ncores <- nchildren
+
+    ## However, ...
+    if (nfutures == 0L) {
+      warning(sprintf("Hmm... %d active multicore processes were detected, but without any active multicore futures (it is not clear by what mechanism they were created). Because of this, the 'future' package do not know how to resolve/collect them and will therefore threat them as they do not exist.", nchildren))
+      ncores <- 0L
+    }
+  }
+
+  return(ncores + 1L)
+}
+
+
+
+#' Request a core for multicore processing
+#'
+#' If no cores are available, the current process
+#' blocks until a core is available.
+#'
+#' @param await A function used to try to "collect"
+#'        finished multicore subprocesses.
+#' @param workers Total number of workers available.
+#' @param times Then maximum number of times subprocesses
+#'        should be collected before timeout.
+#' @param delta Then base interval (in seconds) to wait
+#'        between each try.
+#' @param alpha A multiplicative factor used to increase
+#'        the wait interval after each try.
+#'
+#' @return Invisible TRUE. If no cores are available after
+#'         extensive waiting, then a timeout error is thrown.
+#'
+#' @keywords internal
+requestCore <- function(await, workers=availableCores(), times=getOption("future.wait.times", 1000), delta=getOption("future.wait.interval", 1.0), alpha=getOption("future.wait.alpha", 1.01)) {
+  stopifnot(length(workers) == 1L, is.numeric(workers), is.finite(workers), workers >= 1)
+  stopifnot(is.function(await))
+  times <- as.integer(times)
+  stopifnot(is.finite(times), times > 0)
+  stopifnot(is.finite(alpha), alpha > 0)
+
+  mdebug(sprintf("requestCore(): workers = %d", workers))
+
+  ## No additional cores available?
+  if (workers == 1L) {
+    stop("INTERNAL ERROR: requestCore() was asked to find a free core, but there is only one core available, which is already occupied by the main R process.")
+  }
+
+  iter <- 1L
+  interval <- delta
+  finished <- FALSE
+  while (iter <= times) {
+    used <- usedCores()
+    finished <- (used < workers)
+    if (finished) break
+
+    mdebug(sprintf("usedCores() = %d, workers = %d", used, workers))
+
+    ## Wait
+    Sys.sleep(interval)
+
+    ## Finish/close cores, iff possible
+    await()
+
+    interval <- alpha*interval
+    iter <- iter + 1L
+  }
+
+  if (!finished) {
+    msg <- sprintf("TIMEOUT: All %d CPU cores are still occupied", workers)
+    mdebug(msg)
+    stop(msg)
+  }
+
+  invisible(finished)
+}
diff --git a/R/multiprocess.R b/R/multiprocess.R
new file mode 100644
index 0000000..6fbc66a
--- /dev/null
+++ b/R/multiprocess.R
@@ -0,0 +1,39 @@
+#' Create a multiprocess future whose value will be resolved asynchroneously using multicore or a multisession evaluation
+#'
+#' A multiprocess future is a future that uses \link{multicore} evaluation
+#' if supported, otherwise it uses \link{multisession} evaluation.
+#' Regardless, its \emph{value is computed and resolved in
+#' parallel in another process}.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done and from which globals are obtained.
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param globals If TRUE, global objects are validated at the point
+#' in time when the future is created (always before it is resolved),
+#' that is, they identified and located.  If some globals fail to be
+#' located, an informative error is generated.
+#' @param workers The maximum number of multiprocess futures that
+#' can be active at the same time before blocking.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param earlySignal Specified whether conditions should be signaled as soon as possible or not.
+#' @param \dots Not used.
+#'
+#' @return A \link{MultiprocessFuture} implemented as either a
+#' \link{MulticoreFuture} or a \link{MultisessionFuture}.
+#'
+#' @example incl/multiprocess.R
+#'
+#' @seealso
+#' Internally \code{\link{multicore}()} and \code{\link{multisession}()}
+#' are used.
+#'
+#' @export
+multiprocess <- function(expr, envir=parent.frame(), substitute=TRUE, globals=TRUE, workers=availableCores(), gc=FALSE, earlySignal=FALSE, ...) {
+  if (substitute) expr <- substitute(expr)
+  fun <- if (supportsMulticore()) multicore else multisession
+  fun(expr=expr, envir=envir, substitute=FALSE, globals=globals, workers=workers, gc=gc, earlySignal=earlySignal, ...)
+}
+class(multiprocess) <- c("multiprocess", "future", "function")
diff --git a/R/multisession.R b/R/multisession.R
new file mode 100644
index 0000000..ccd80fe
--- /dev/null
+++ b/R/multisession.R
@@ -0,0 +1,92 @@
+#' Create a multisession future whose value will be resolved asynchroneously in a parallel R session
+#'
+#' A multisession future is a future that uses multisession evaluation,
+#' which means that its \emph{value is computed and resolved in
+#' parallel in another R session}.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done and from which globals are obtained.
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param persistent If FALSE, the evaluation environment is cleared
+#' from objects prior to the evaluation of the future.
+#' @param workers The maximum number of multisession futures that
+#' can be active at the same time before blocking.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param earlySignal Specified whether conditions should be signaled as soon as possible or not.
+#' @param \dots Not used.
+#'
+#' @return A \link{MultisessionFuture}.
+#' If \code{workers == 1}, then all processing using done in the
+#' current/main R session and we therefore fall back to using
+#' a lazy future.
+#'
+## FIXME: It seem that multisession futures in examples gives errors
+##        with R CMD check, e.g. "cannot open file 'future-Ex.Rout':
+##        Permission denied".  Because of this we use \donttest{}.
+#'@example incl/multisession.R
+#'
+#' @details
+#' This function will block if all available R session are occupied
+#' and will be unblocked as soon as one of the already running
+#' multisession futures is resolved.  For the total number of
+#' R sessions available including the current/main R process, see
+#' \code{\link{availableCores}()}.
+#'
+#' A multisession future is a special type of cluster future.
+#'
+#' The preferred way to create an multisession future is not to call
+#' this function directly, but to register it via
+#' \code{\link{plan}(multisession)} such that it becomes the default
+#' mechanism for all futures.  After this \code{\link{future}()}
+#' and \code{\link{\%<=\%}} will create \emph{multisession futures}.
+#'
+#' @section Known issues:
+#' In the current implementation, \emph{all} background R sessions
+#' are allocated and launched in the background \emph{as soon as the
+#' first multisession future is created}. This means that more R
+#' sessions may be running than what will ever be used.
+#' The reason for this is that background sessions are currently
+#' created using \code{\link[parallel:makeCluster]{makeCluster}()},
+#' which requires that all R sessions are created at once.
+#'
+#' @seealso
+#' For processing in multiple forked R sessions, see
+#' \link{multicore} futures.
+#' For multicore processing with fallback to multisession where
+#' the former is not supported, see \link{multiprocess} futures.
+#'
+#' Use \code{\link{availableCores}()} to see the total number of
+#' cores that are available for the current R session.
+#'
+#' @export
+multisession <- function(expr, envir=parent.frame(), substitute=TRUE, persistent=FALSE, workers=availableCores(), gc=FALSE, earlySignal=FALSE, ...) {
+  ## BACKWARD COMPATIBILITY
+  args <- list(...)
+  if ("maxCores" %in% names(args)) {
+    workers <- args$maxCores
+    .Deprecated(msg="Argument 'maxCores' has been renamed to 'workers'. Please update you script/code that uses the future package.")
+  }
+
+  if (substitute) expr <- substitute(expr)
+  workers <- as.integer(workers)
+  stopifnot(length(workers) == 1, is.finite(workers), workers >= 1)
+
+  ## Fall back to eager futures if only a single R session can be used,
+  ## i.e. the use the current main R process.
+  if (workers == 1L) {
+    ## FIXME: How to handle argument 'persistent'? /HB 2016-03-19
+    return(lazy(expr, envir=envir, substitute=FALSE, globals=TRUE, local=TRUE))
+  }
+
+  ## IMPORTANT: When we setup a multisession cluster, we need to
+  ## account for the main R process as well, i.e. we should setup
+  ## a cluster with one less process.
+  workers <- ClusterRegistry("start", workers=workers-1L)
+
+  future <- MultisessionFuture(expr=expr, envir=envir, substitute=FALSE, persistent=persistent, workers=workers, gc=gc, earlySignal=earlySignal, ...)
+  run(future)
+}
+class(multisession) <- c("multisession", "cluster", "multiprocess", "future", "function")
diff --git a/R/nbrOfWorkers.R b/R/nbrOfWorkers.R
new file mode 100644
index 0000000..bbdfbf7
--- /dev/null
+++ b/R/nbrOfWorkers.R
@@ -0,0 +1,37 @@
+#' Gets the number of workers
+#'
+#' @param evaluator A future evaluator function.
+#' If NULL (default), the current evaluator as returned
+#' by \code{\link{plan}()} is used.
+#'
+#' @return A number in [1,Inf].
+#'
+#' @export
+nbrOfWorkers <- function(evaluator=NULL) {
+  UseMethod("nbrOfWorkers")
+}
+
+
+#' @export
+nbrOfWorkers.uniprocess <- function(evaluator) 1L
+
+#' @export
+nbrOfWorkers.multiprocess <- function(evaluator) {
+  expr <- formals(evaluator)$workers
+  workers <- eval(expr)
+  stopifnot(length(workers) == 1, is.finite(workers), workers >= 1)
+  workers
+}
+
+#' @export
+nbrOfWorkers.future <- function(evaluator) {
+  expr <- formals(evaluator)$workers
+  workers <- eval(expr)
+  if (is.null(workers)) workers <- Inf
+  workers
+}
+
+#' @export
+nbrOfWorkers.NULL <- function(evaluator) {
+  nbrOfWorkers(plan())
+}
diff --git a/R/options.R b/R/options.R
new file mode 100644
index 0000000..89f2ca0
--- /dev/null
+++ b/R/options.R
@@ -0,0 +1,50 @@
+#' Options used for futures
+#'
+#' Below are all \R options that are currently used by the \pkg{future} package and packages enhancing it.\cr
+#' \cr
+#' \emph{WARNING: Note that the names and the default values of these options may change in future versions of the package.  Please use with care until further notice.}
+#'
+#' @section Options for controlling futures:
+#' \describe{
+#'  \item{\option{future.plan}:}{Default future strategy plan used unless otherwise specified via \code{\link{plan}()}. This will also be the future plan set when calling \code{plan("default")}.  If not specified, this option may be set when the \pkg{future} package is \emph{loaded} if command-line option \code{--parallel=ncores} (short \code{-p ncores}) is specified; if \code{ncores > 1}, then option \option{future.plan} is set to \code{multiprocess} otherwise \code{eager} (in addition  [...]
+#'  \item{\option{future.globals.onMissing}:}{Action to take when non-existing global variables ("globals" or "unknowns") are identified when the future is created.  If \code{"error"}, an error is generated immediately.  If \code{"ignore"}, no action is taken and an attempt to evaluate the future expression will be made.  The latter is useful when there is a risk for false-positive globals being identified, e.g. when future expression contains non-standard evaluation (NSE).  (Default: \c [...]
+#'  \item{\option{future.globals.method}:}{Method used to identify globals. For details, see \code{\link[globals]{globalsOf}()}. (Default: \code{"ordered"})}
+#'  \item{\option{future.globals.maxSize}:}{Maximum allowed total size (in bytes) of global variables identified. Used to prevent too large exports. (Default: \code{500*1024^2} = 500 MiB)}
+#'  \item{\option{future.globals.resolve}:}{If \code{TRUE}, globals that are \code{\link{Future}} objects (typically created as \emph{explicit} futures) will be resolved and have their values (using \code{value()}) collected.  Because searching for unresolved futures among globals (including their content) can be expensive, the default is not to do it and instead leave it to the run-time checks that assert proper ownership when resolving futures and collecting their values. (Default: \co [...]
+#'  \item{\option{future.resolve.recursive}:}{An integer specifying the maximum recursive depth to which futures should be resolved. If negative, nothing is resolved.  If \code{0}, only the future itself is resolved.  If \code{1}, the future and any of its elements that are futures are resolved, and so on. If \code{+Inf}, infinite search depth is used. (Default: \code{0})}
+#'  \item{\option{future.wait.times}:}{Maximum number of times a future is polled waiting for it to be resolved.}
+#'  \item{\option{future.wait.interval}:}{Initial interval (in seconds) between polls.}
+#'  \item{\option{future.wait.alpha}:}{Positive scale factor used to increase the interval after each poll. (Default: \code{0.01})}
+#' }
+#'
+#' @section Options for debugging futures:
+#' \describe{
+#'  \item{\option{future.debug}:}{If \code{TRUE}, extensive debug messages are generated. (Default: \code{FALSE})}
+#'  \item{\option{future.progress}:}{If \code{TRUE}, progress is displayed while blocked waiting for futures to be resolved. (Default: \code{FALSE})}
+#' }
+#'
+#' @section Options for controlling package startup:
+#' \describe{
+#'  \item{\option{future.startup.script}:}{If \code{FALSE}, any \file{.future.R} startup scripts, which may exist in the current directory and / or the user's home directory, are ignored. Such startup scripts are otherwise sourced when the \pkg{future} package is \emph{attached}. \emph{Importantly}, this option is \emph{always} set to \code{FALSE} if the \pkg{future} package is loaded as part of a future expression being evaluated, e.g. in a background process. In order words, they are s [...]
+#'  \item{\option{future.cmdargs}:}{Overrides \code{\link[base]{commandArgs}()} when the \pkg{future} package is \emph{loaded}.}
+#' }
+#'
+#' @section Options for configurating low-level system behaviors:
+#' \describe{
+#'  \item{\option{future.availableCores.methods}:}{Default lookup methods for \code{\link{availableCores}()}. (Default: \code{c("system", "mc.cores+1", "_R_CHECK_LIMIT_CORES_", "Slurm", "PBS", "SGE")})}
+#'  \item{\option{future.availableCores.system}:}{Number of "system" cores used instead of what is reported by \code{\link{availableCores}(which="system")}. If not specified, this option is set according to system environment variable \env{R_FUTURE_AVAILABLECORES_SYSTEM} when the \pkg{future} package is \emph{loaded}.}
+#' }
+#'
+#' @section Options for demos:
+#' \describe{
+#'  \item{\option{future.demo.mandelbrot.region}:}{Either a named list of \code{\link{mandelbrot}()} arguments or an integer in [1,3] specifying a predefined Mandelbrot region. (Default: \code{1L})}
+#'  \item{\option{future.demo.mandelbrot.nrow}:}{Number of rows and columns of tiles. (Default: \code{3L})}
+#' }
+#'
+#' @seealso
+#' To set \R options when \R starts (even before the \pkg{future} package is loaded), see the \link[base]{Startup} help page.
+#'
+#' @aliases future.availableCores.methods future.cmdargs future.cores future.debug future.globals.maxSize future.globals.method future.globals.onMissing future.globals.resolve future.plan future.progress future.resolve.recursive future.startup.script future.wait.alpha future.wait.interval future.wait.times R_FUTURE_PLAN R_FUTURE_CORES future.demo.mandelbrot.region future.demo.mandelbrot.nrow
+#' @keywords internal
+#' @name future.options
+NULL
diff --git a/R/plan.R b/R/plan.R
new file mode 100644
index 0000000..59b963f
--- /dev/null
+++ b/R/plan.R
@@ -0,0 +1,208 @@
+#' Plan how to resolve a future
+#'
+#' This function allows you to plan the future, more specifically,
+#' it specifies how \code{\link{future}()}:s are resolved,
+#' e.g. sequentially or in parallel.
+#'
+#' @param strategy The evaluation function (or name of it) to use
+#' for resolving a future.  If NULL, then the current strategy is returned.
+#' @param \dots Additional arguments overriding the default arguments
+#' of the evaluation function.
+#' @param substitute If TRUE, the \code{strategy} expression is
+#' \code{substitute()}:d, otherwise not.
+#' @param .call (internal) Used for recording the call to this function.
+#'
+#' @return If a new strategy is chosen, then the previous one is returned
+#' (invisible), otherwise the current one is returned (visibly).
+#'
+#' @example incl/plan.R
+#'
+#' @details
+#' The default strategy is \code{\link{eager}}, but the default can be
+#' configured by option \option{future.plan} and, if that is not set,
+#' system environment variable \env{R_FUTURE_PLAN}.
+#' To reset the strategy back to the default, use \code{plan("default")}.
+#'
+#' @section Implemented evaluation strategies:
+#' \itemize{
+#'  \item{\code{\link{eager}}:}{
+#'    Resolves futures sequentially in the current R process.
+#'  }
+#'  \item{\code{\link{lazy}}:}{
+#'    Resolves futures synchronously (sequentially) in the current
+#'    R process, but only if their values are requested.  Futures for
+#'    which the values are never requested will not be evaluated.
+#'  }
+#'  \item{\code{\link{transparent}}:}{
+#'    Resolves futures synchronously (sequentially) in the current
+#'    R process and assignments will be done to the calling environment.
+#'    Early stopping is enabled by default.
+#'  }
+#'  \item{\code{\link{multisession}}:}{
+#'    Resolves futures asynchronously (in parallel) in separate
+#'    R sessions running in the background on the same machine.
+#'  }
+#'  \item{\code{\link{multicore}}:}{
+#'    Resolves futures asynchronously (in parallel) in separate
+#'    \emph{forked} R processes running in the background on
+#'    the same machine.  Not supported on Windows.
+#'  }
+#'  \item{\code{\link{multiprocess}}:}{
+#'    If multicore evaluation is supported, that will be used,
+#     otherwise multisession evaluation will be used.
+#'  }
+#'  \item{\code{\link{cluster}}:}{
+#'    Resolves futures asynchronously (in parallel) in separate
+#'    R sessions running typically on one or more machines.
+#'  }
+#'  \item{\code{\link{remote}}:}{
+#'    Resolves futures asynchronously in a separate R session
+#'    running on a separate machine, typically on a different
+#'    network.
+#'  }
+#' }
+#'
+#' Other package may provide additional evaluation strategies.
+#' Notably, the \pkg{future.BatchJobs} package implements a
+#' type of futures that will be resolved via job schedulers
+#' that are typically available on high-performance compute
+#' (HPC) clusters, e.g. LSF, Slurm, TORQUE/PBS, Sun Grid Engine,
+#' and OpenLava.
+#'
+#' @export
+plan <- local({
+  defaultStrategy <- structure(eager, call=substitute(plan(eager)))
+
+  ## Stack of type of futures to use
+  stack <- list(defaultStrategy)
+
+  ## Main function
+  function(strategy=NULL, ..., substitute=TRUE, .call=TRUE) {
+    if (substitute) strategy <- substitute(strategy)
+    if (is.logical(.call)) stopifnot(length(.call) == 1L, !is.na(.call))
+
+    ## Predefined "actions":
+    if (is.null(strategy) || identical(strategy, "next")) {
+      ## Next future strategy?
+      return(stack[[1L]])
+    } else if (identical(strategy, "default")) {
+      strategy <- getOption("future.plan", eager)
+    } else if (identical(strategy, "list")) {
+      ## List stack of future strategies?
+      return(stack)
+    } else if (identical(strategy, "reset")) {
+      ## Rest stack of future strategies?
+      stack <<- list(defaultStrategy)
+      return(stack)
+    } else if (identical(strategy, "pop")) {
+      ## Pop strategy stack and return old stack (so it can be pushed back later)
+      oldStack <- stack
+      stack <<- stack[-1L]
+      if (length(stack) == 0L) stack <<- list(defaultStrategy)
+      return(oldStack)
+    }
+
+    ## Current and new stack of future strategies
+    oldStack <- stack
+    newStack <- NULL
+
+    ## Set new stack?
+    if (is.list(strategy)) {
+      stopifnot(is.list(strategy), length(strategy) >= 1L)
+      for (ii in seq_along(strategy)) {
+        stopifnot(is.function(strategy[[ii]]))
+      }
+      stack <<- strategy
+      return(invisible(oldStack[[1L]]))
+    }
+
+    ## (a) Is a (plain) list of future strategies specified?
+    if (is.language(strategy)) {
+      first <- as.list(strategy)[[1]]
+      if (is.symbol(first)) {
+        first <- eval(first, envir=parent.frame())
+        ## A list object, e.g. plan(oplan)?
+        if (is.list(first)) {
+          strategies <- first
+          res <- plan(strategies, substitute=FALSE)
+          return(invisible(res))
+        }
+
+        ## Example: plan(list(eager, lazy))
+        if (is.function(first) && identical(first, list)) {
+          ## Specified explicitly using plan(list(...))?
+          strategies <- eval(strategy, envir=parent.frame())
+          stopifnot(is.list(strategies), length(strategies) >= 1L)
+          ## Coerce strings to functions, e.g. plan(list("eager", lazy))
+          for (kk in seq_along(strategies)) {
+            strategy_kk <- strategies[[kk]]
+            if (is.character(strategy_kk)) {
+              strategy_kk <- tweak(strategy_kk, penvir=parent.frame())
+              strategies[[kk]] <- strategy_kk
+            }
+          }
+          newStack <- strategies
+        }
+      }
+    }
+
+    ## (b) Otherwise, assume a single future strategy
+    if (is.null(newStack)) {
+      ## Arguments to be tweaked
+      targs <- list(...)
+
+      if (is.symbol(strategy)) {
+        strategy <- eval(strategy, envir=parent.frame())
+      } else if (is.language(strategy)) {
+        strategyT <- as.list(strategy)
+
+        ## tweak(...)?
+        if (strategyT[[1]] == as.symbol("tweak")) {
+          strategy <- eval(strategy, envir=parent.frame())
+        } else {
+          isSymbol <- sapply(strategyT, FUN=is.symbol)
+          if (!all(isSymbol)) {
+            targs <- c(targs, strategyT[-1L])
+            strategy <- strategyT[[1L]]
+          }
+          strategy <- eval(strategy, envir=parent.frame())
+        }
+      }
+
+      ## Tweak future strategy accordingly
+      args <- c(list(strategy), targs, penvir=parent.frame())
+      tstrategy <- do.call(tweak, args=args)
+
+      ## Setup a new stack of future strategies (with a single one)
+      newStack <- list(tstrategy)
+    }
+
+
+    ## Attach call attribute to each strategy in the stack?
+    if (!is.null(.call)) {
+      ## The call to assign
+      call <- if (isTRUE(.call)) sys.call() else .call
+
+      for (kk in seq_along(newStack)) {
+        strategy <- newStack[[kk]]
+        ## Skip if already has a call attibute
+        if (!is.null(attr(strategy, "call"))) next
+        ## Attach call
+        attr(strategy, "call") <- call
+        newStack[[kk]] <- strategy
+      }
+    }
+
+    ## Set new strategy for futures
+    stack <<- newStack
+    stopifnot(is.list(stack), length(stack) >= 1L)
+
+    invisible(oldStack[[1L]])
+  } # function()
+}) # plan()
+
+
+supportedStrategies <- function(strategies=c("lazy", "eager", "multicore", "multisession", "multiprocess")) {
+  if (!supportsMulticore()) strategies <- setdiff(strategies, "multicore")
+  strategies
+}
diff --git a/R/plan_OP.R b/R/plan_OP.R
new file mode 100644
index 0000000..f941c60
--- /dev/null
+++ b/R/plan_OP.R
@@ -0,0 +1,25 @@
+#' Use a specific plan for a future assignment
+#'
+#' @usage fassignment \%plan\% strategy
+#'
+#' @param fassignment The future assignment, e.g.
+#'        \code{x \%<=\% \{ expr \}}.
+#' @param strategy The mechanism for how the future should be
+#'        resolved. See \code{\link{plan}()} for further details.
+#'
+#' @seealso
+#' The \code{\link{plan}()} function sets the default plan for all futures.
+#'
+#' @export
+`%plan%` <- function(fassignment, strategy) {
+  fassignment <- substitute(fassignment)
+  strategy <- substitute(strategy)
+  envir <- parent.frame(1)
+
+  ## Temporarily use a different plan
+  oplan <- plan("list")
+  on.exit(plan(oplan, substitute=FALSE, .call=NULL))
+  plan(strategy, substitute=FALSE, .call=NULL)
+
+  eval(fassignment, envir=envir)
+}
diff --git a/R/remote.R b/R/remote.R
new file mode 100644
index 0000000..71c559e
--- /dev/null
+++ b/R/remote.R
@@ -0,0 +1,63 @@
+#' Create a remote future whose value will be resolved asynchroneously in a remote process
+#'
+#' A remote future is a future that uses remote cluster evaluation,
+#' which means that its \emph{value is computed and resolved
+#' remotely in another process}.
+#'
+#' @param expr An R \link[base]{expression}.
+#' @param envir The \link{environment} in which the evaluation
+#' is done and from which globals are obtained.
+#' @param substitute If TRUE, argument \code{expr} is
+#' \code{\link[base]{substitute}()}:ed, otherwise not.
+#' @param persistent If FALSE, the evaluation environment is cleared
+#' from objects prior to the evaluation of the future.
+#' @param workers A cluster object created by
+#' \code{\link[parallel]{makeCluster}()}.
+#' @param gc If TRUE, the garbage collector run after the future
+#' is resolved (in the process that evaluated the future).
+#' @param earlySignal Specified whether conditions should be signaled as soon as possible or not.
+#' @param myip The external IP address of this machine.
+#' If NULL, then it is inferred using an online service (default).
+#' @param \dots Not used.
+#'
+#' @return A \link{ClusterFuture}.
+#'
+#' @example incl/remote.R
+#'
+#' @details
+#' Note that remote futures use \code{persistent=TRUE} by default.
+#'
+#' @export
+remote <- function(expr, envir=parent.frame(), substitute=TRUE, persistent=TRUE, workers=NULL, gc=FALSE, earlySignal=FALSE, myip=NULL, ...) {
+  if (substitute) expr <- substitute(expr)
+
+  stopifnot(length(workers) >= 1L, is.character(workers), !anyNA(workers))
+
+  if (is.character(workers)) {
+    ## Guess what type of IP to use
+    if (is.null(myip)) {
+      if (all(workers %in% c("localhost", "127.0.0.1"))) {
+        ## For conveniency, if all workers are on the localhost,
+	## then we know that localhost should be used
+        myip <- "127.0.0.1"
+      } else {
+        myip <- "<external>"
+      }
+    }
+    stopifnot(length(myip) == 1, is.character(myip), !is.na(myip))
+    
+    if (myip == "<external>") {
+      myip <- myExternalIP()
+    } else if (myip == "<internal>") {
+      myip <- myInternalIP()
+    }
+    
+    workers <- ClusterRegistry("start", workers=workers, master=myip, homogeneous=FALSE)
+  } else if (!inherits(workers, "cluster")) {
+    stop("Argument 'workers' is not of class 'cluster': ", class(workers)[1])
+  }
+
+  future <- ClusterFuture(expr=expr, envir=envir, substitute=FALSE, persistent=persistent, workers=workers, gc=gc, earlySignal=earlySignal, ...)
+  run(future)
+}
+class(remote) <- c("remote", "multiprocess", "future", "function")
diff --git a/R/resolve.R b/R/resolve.R
new file mode 100644
index 0000000..c09ab2d
--- /dev/null
+++ b/R/resolve.R
@@ -0,0 +1,376 @@
+#' Wait until all existing futures in an environment are resolved
+#'
+#' The environment is first scanned for futures and then the futures
+#' are polled until all are resolved.  When a resolved future is
+#' detected its value is retrieved (optionally).
+#' This provides an efficient mechanism for waiting for a set of
+#' futures to be resolved and in the meanwhile retrieving values
+#' of already resolved futures.
+#'
+#' @param x an environment holding futures.
+#' @param idxs subset of elements to check.
+#' @param value If TRUE, the values are retrieved, otherwise not.
+#' @param recursive A non-negative number specifying how deep of
+#' a recursion should be done.  If TRUE, an infintive recursion
+#' is used.  If FALSE or zero, no recursion is performed.
+#' @param sleep Number of seconds to wait before checking
+#' if futures have been resolved since last time.
+#' @param progress If TRUE textual progress summary is outputted.
+#' If a function, the it is called as \code{progress(done, total)}
+#' every time a future is resolved.
+#' @param ... Not used
+#'
+#' @return Returns \code{x} (regardless of subsetting or not).
+#'
+#' @seealso futureOf
+#'
+#' @export
+resolve <- function(x, idxs=NULL, value=FALSE, recursive=0, sleep=1.0, progress=getOption("future.progress", FALSE), ...) UseMethod("resolve")
+
+#' @export
+resolve.default <- function(x, ...) x
+
+#' @export
+resolve.Future <- function(x, idxs=NULL, value=FALSE, recursive=0, sleep=0.1, progress=getOption("future.progress", FALSE), ...) {
+  if (is.logical(recursive)) {
+    if (recursive) recursive <- getOption("future.resolve.recursive", 99)
+  }
+  recursive <- as.numeric(recursive)
+  
+  ## Nothing to do?
+  if (recursive < 0) return(x)
+
+  ## Poll for Future to finish
+  while (!resolved(x)) {
+    Sys.sleep(sleep)
+  }
+
+  msg <- sprintf("A %s was resolved", class(x)[1])
+
+  if (value) {
+    ## Allow for errors
+    msg <- tryCatch({
+      v <- x$value
+      if (is.null(v)) {
+        v <- value(x)
+
+        msg <- sprintf("%s and its value was collected", msg)
+
+        ## Recursively resolve the value?
+	if (!is.atomic(v)) {
+          v <- resolve(v, value=TRUE, recursive=recursive-1, sleep=sleep, progress=FALSE, ...)
+	  msg <- sprintf("%s (and resolved itself)", msg)
+	}
+
+        msg
+      } else {
+        sprintf("%s and its value was already collected", msg)
+      }
+    }, error = function(ex) {
+      sprintf("%s but failed to collect its value", msg)
+    })
+  } else {
+    msg <- sprintf("%s (value was not collected)", msg)
+  }
+
+  mdebug(msg)
+
+  x
+} ## resolve() for Future
+
+
+#' @export
+resolve.list <- function(x, idxs=NULL, value=FALSE, recursive=0, sleep=0.1, progress=getOption("future.progress", FALSE), ...) {
+  if (is.logical(recursive)) {
+    if (recursive) recursive <- getOption("future.resolve.recursive", 99)
+  }
+  recursive <- as.numeric(recursive)
+  
+  ## Nothing to do?
+  if (recursive < 0) return(x)
+
+  ## Nothing to do?
+  if (length(x) == 0) return(x)
+
+  x0 <- x
+
+  hasProgress <- ((is.logical(progress) && progress) || is.function(progress))
+
+  ## Setup default progress function?
+  if (hasProgress && !is.function(progress)) {
+    progress <- function(done, total) {
+      msg <- sprintf("Progress: %.0f%% (%d/%d)", 100*done/total, done, total)
+      if (done < total) {
+        bs <- paste(rep("\b", times=nchar(msg)), collapse="")
+        message(paste(msg, bs, sep=""), appendLF=FALSE)
+      } else {
+        message(msg)
+      }
+    } ## progress()
+  }
+
+
+  ## Subset?
+  if (!is.null(idxs)) {
+    ## Nothing to do?
+    if (length(idxs) == 0) return(x)
+
+    ## Multi-dimensional indices?
+    if (is.matrix(idxs)) {
+      idxs <- whichIndex(idxs, dim=dim(x), dimnames=dimnames(x))
+    }
+    idxs <- unique(idxs)
+
+    if (is.numeric(idxs)) {
+      idxs <- as.numeric(idxs)
+      if (any(idxs < 1 | idxs > length(x))) {
+        stop(sprintf("Indices out of range [1,%d]: %s", length(x), hpaste(idxs)))
+      }
+    } else {
+      names <- names(x)
+      if (is.null(names)) {
+        stop("Named subsetting not possible. Elements are not named.")
+      }
+
+      idxs <- as.character(idxs)
+      unknown <- idxs[!is.element(idxs, names)]
+      if (length(unknown) > 0) {
+        stop("Unknown elements: ", hpaste(sQuote(unknown)))
+      }
+    }
+
+    x <- x[idxs]
+  }
+
+  mdebug("resolve() on list ...")
+  mdebug(" recursive: %s", recursive)
+
+  ## Everything is considered non-resolved by default
+  nx <- length(x)
+
+  ## Total number of values to resolve
+  total <- nx
+  remaining <- seq_len(nx)
+
+  if (hasProgress) {
+    done0 <- done <- 0
+    progress(done, total)
+  }
+
+  mdebug(" length: %d", nx)
+  mdebug(" elements: %s", hpaste(sQuote(names(x))))
+
+  ## Resolve all elements
+  while (length(remaining) > 0) {
+    for (ii in remaining) {
+      obj <- x[[ii]]
+
+      if (!is.atomic(obj)) {
+        ## If an unresolved future, move on to the next object
+        ## so that future can be resolved in the asynchroneously
+        if (inherits(obj, "Future") && !resolved(obj)) next
+
+        ## In all other cases, try to resolve
+        resolve(obj, value=value, recursive=recursive-1, sleep=sleep, progress=FALSE, ...)
+      }
+
+      ## Assume resolved at this point
+      remaining <- setdiff(remaining, ii)
+      mdebug(" length: %d (resolved future %s)", length(remaining), ii)
+      stopifnot(!anyNA(remaining))
+
+      if (hasProgress) {
+        done <- total - length(remaining)
+        progress(done, total)
+      }
+    } # for (ii ...)
+
+    ## Wait a bit before checking again
+    if (length(remaining) > 0) Sys.sleep(sleep)
+  } # while (...)
+
+  if (hasProgress && done != done0) progress(done, total)
+
+  mdebug("resolve() on list ... DONE")
+
+  x0
+} ## resolve() for list
+
+
+#' @export
+resolve.environment <- function(x, idxs=NULL, value=FALSE, recursive=0, sleep=0.1, progress=FALSE, ...) {
+  if (is.logical(recursive)) {
+    if (recursive) recursive <- getOption("future.resolve.recursive", 99)
+  }
+  recursive <- as.numeric(recursive)
+  
+  ## Nothing to do?
+  if (recursive < 0) return(x)
+
+  ## Nothing to do?
+  if (length(x) == 0) return(x)
+
+  ## Subset?
+  if (is.null(idxs)) {
+    ## names(x) is only supported in R (>= 3.2.0)
+    idxs <- ls(envir=x, all.names=TRUE)
+  } else {
+    ## Nothing to do?
+    if (length(idxs) == 0) return(x)
+
+    ## names(x) is only supported in R (>= 3.2.0)
+    names <- ls(envir=x, all.names=TRUE)
+
+    ## Sanity check (because length(x) == 0 returns early above)
+    stopifnot(length(names) > 0)
+
+    idxs <- unique(idxs)
+
+    idxs <- as.character(idxs)
+    unknown <- idxs[!is.element(idxs, names)]
+    if (length(unknown) > 0) {
+      stop("Unknown elements: ", hpaste(sQuote(unknown)))
+    }
+  }
+
+
+  ## Nothing to do?
+  nx <- length(idxs)
+  if (nx == 0) return(x)
+
+  mdebug("resolve() on environment ...")
+  mdebug(" recursive: %s", recursive)
+
+  ## Coerce future promises into Future objects
+  x0 <- x
+  x <- futures(x)
+  nx <- length(x)
+  idxs <- ls(envir=x, all.names=TRUE)
+  stopifnot(length(idxs) == nx)
+
+  ## Everything is considered non-resolved by default
+  remaining <- idxs
+
+  mdebug(" elements: [%d] %s", nx, hpaste(sQuote(idxs)))
+
+  ## Resolve all elements
+  while (length(remaining) > 0) {
+    for (ii in remaining) {
+      obj <- x[[ii]]
+
+      if (!is.atomic(obj)) {
+        ## If an unresolved future, move on to the next object
+        ## so that future can be resolved in the asynchroneously
+        if (inherits(obj, "Future") && !resolved(obj)) next
+
+        ## In all other cases, try to resolve
+        resolve(obj, value=value, recursive=recursive-1, sleep=sleep, progress=FALSE, ...)
+      }
+
+      ## Assume resolved at this point
+      remaining <- setdiff(remaining, ii)
+      mdebug(" length: %d (resolved future %s)", length(remaining), ii)
+      stopifnot(!anyNA(remaining))
+    } # for (ii ...)
+
+    ## Wait a bit before checking again
+    if (length(remaining) > 0) Sys.sleep(sleep)
+  } # while (...)
+
+  mdebug("resolve() on environment ... DONE")
+
+  x0
+} ## resolve() for environment
+
+
+#' @export
+resolve.listenv <- function(x, idxs=NULL, value=FALSE, recursive=0, sleep=0.1, progress=FALSE, ...) {
+  if (is.logical(recursive)) {
+    if (recursive) recursive <- getOption("future.resolve.recursive", 99)
+  }
+  recursive <- as.numeric(recursive)
+  
+  ## Nothing to do?
+  if (recursive < 0) return(x)
+
+  ## Nothing to do?
+  if (length(x) == 0) return(x)
+
+  ## Subset?
+  if (is.null(idxs)) {
+    idxs <- seq_along(x)
+  } else {
+    ## Nothing to do?
+    if (length(idxs) == 0) return(x)
+
+    ## Multi-dimensional indices?
+    if (is.matrix(idxs)) {
+      idxs <- whichIndex(idxs, dim=dim(x), dimnames=dimnames(x))
+    }
+    idxs <- unique(idxs)
+
+    if (is.numeric(idxs)) {
+      if (any(idxs < 1 | idxs > length(x))) {
+        stop(sprintf("Indices out of range [1,%d]: %s", length(x), hpaste(idxs)))
+      }
+    } else {
+      names <- names(x)
+      
+      ## Sanity check (because length(x) == 0 returns early above)
+      stopifnot(length(names) > 0)
+
+      idxs <- as.character(idxs)
+      unknown <- idxs[!is.element(idxs, names)]
+      if (length(unknown) > 0) {
+        stop("Unknown elements: ", hpaste(sQuote(unknown)))
+      }
+    }
+  }
+
+  ## Nothing to do?
+  nx <- length(idxs)
+  if (nx == 0) return(x)
+
+
+  mdebug("resolve() on list environment ...")
+  mdebug(" recursive: %s", recursive)
+
+  ## Coerce future promises into Future objects
+  x0 <- x
+  x <- futures(x)
+  nx <- length(x)
+
+  ## Everything is considered non-resolved by default
+  remaining <- seq_len(nx)
+
+  mdebug(" length: %d", nx)
+  mdebug(" elements: %s", hpaste(sQuote(names(x))))
+
+  ## Resolve all elements
+  while (length(remaining) > 0) {
+    for (ii in remaining) {
+      obj <- x[[ii]]
+
+      if (!is.atomic(obj)) {
+        ## If an unresolved future, move on to the next object
+        ## so that future can be resolved in the asynchroneously
+        if (inherits(obj, "Future") && !resolved(obj)) next
+
+        ## In all other cases, try to resolve
+        resolve(obj, value=value, recursive=recursive-1, sleep=sleep, progress=FALSE, ...)
+      }
+
+      ## Assume resolved at this point
+      remaining <- setdiff(remaining, ii)
+      mdebug(" length: %d (resolved future %s)", length(remaining), ii)
+      stopifnot(!anyNA(remaining))
+    } # for (ii ...)
+
+    ## Wait a bit before checking again
+    if (length(remaining) > 0) Sys.sleep(sleep)
+  } # while (...)
+
+  mdebug("resolve() on list environment ... DONE")
+
+  x0
+} ## resolve() for list environment
diff --git a/R/resolved.R b/R/resolved.R
new file mode 100644
index 0000000..4dbf8a7
--- /dev/null
+++ b/R/resolved.R
@@ -0,0 +1,60 @@
+#' Check whether a future is resolved or not
+#'
+#' @param x A \link{Future}, a list or an environment (which also
+#' includes \link[listenv:listenv]{list environment}.
+#' @param \dots Not used
+#'
+#' @return A logical of the same length and dimensions as \code{x}.
+#' Each element is TRUE unless the corresponding element is a
+#' non-resolved future in case it is FALSE.
+#'
+#' @details
+#' This method needs to be implemented by the class that implement
+#' the Future API.  The implementation must never throw an error,
+#' but only return either TRUE or FALSE.
+#' It should also be possible to use the method for polling the
+#' future until it is resolved (without having to wait infinitly long),
+#' e.g. \code{while (!resolved(future)) Sys.sleep(5)}.
+#'
+#' @export
+#' @export resolved
+#' @aliases resolved.default
+#' @aliases resolved.Future
+#' @aliases resolved.list
+#' @aliases resolved.environment
+resolved <- function(x, ...) UseMethod("resolved")
+
+#' @export
+resolved.default <- function(x, ...) TRUE
+
+#' @export
+resolved.list <- function(x, ...) {
+  fs <- futures(x)
+
+  ## Allocate results. Assume everything
+  ## is resolved unless not.
+  res <- rep(TRUE, times=length(fs))
+  for (ii in seq_along(fs)) {
+    f <- fs[[ii]]
+    if (inherits(f, "Future")) res[[ii]] <- resolved(f)
+  }
+
+  dim <- dim(fs)
+  if (!is.null(dim)) {
+    dim(res) <- dim
+    ## Preserve dimnames and names
+    dimnames(res) <- dimnames(fs)
+  }
+  names(res) <- names(fs)
+
+  res
+}
+
+#' @export
+resolved.environment <- function(x, ...) {
+  fs <- futures(x)
+  names <- names(fs)
+  fs <- as.list(fs)
+  names(fs) <- names
+  resolved(fs)
+}
diff --git a/R/signalEarly.R b/R/signalEarly.R
new file mode 100644
index 0000000..d13aa18
--- /dev/null
+++ b/R/signalEarly.R
@@ -0,0 +1,44 @@
+signalEarly <- function(future, collect=TRUE, ...) {
+  ## Future is not yet launched
+  if (future$state == "created") return(future)
+
+  earlySignal <- future$earlySignal
+
+  ## Don't signal early?
+  if (!earlySignal) return(future)
+
+  mdebug("signalEarly(): Retrieving value ...")
+
+  ## Collect value?
+  if (collect) {
+    mdebug("signalEarly(): v <- value(f, signal=FALSE)")
+    value <- value(future, signal=FALSE)
+  } else {
+    mdebug("signalEarly(): v <- f$value")
+    value <- future$value
+  }
+
+  mdebug("signalEarly(): class(v) = c(%s)", paste(class(value), collapse=", "))
+  mdebug("signalEarly(): Retrieving value ... DONE")
+
+  ## Was a condition caught?
+  if (!inherits(value, "condition")) return(future)
+
+  mdebug("signalEarly(): signalCondition(v)")
+
+  ## Signal detected condition
+  if (inherits(value, "error")) {
+    stop(FutureError(value, future=future))
+  } else if (inherits(value, "warning")) {
+    warning(value)
+  } else if (inherits(value, "message")) {
+    message(value)
+    message("\n")
+  } else {
+    signalCondition(value)
+  }
+
+  mdebug("signalEarly() ... DONE")
+
+  invisible(future)
+}
diff --git a/R/tweak.R b/R/tweak.R
new file mode 100644
index 0000000..07898cc
--- /dev/null
+++ b/R/tweak.R
@@ -0,0 +1,92 @@
+#' Tweaks a future function by adjusting its default arguments
+#'
+#' @param strategy An existing future function or the name of one.
+#' @param ... Named arguments to replace the defaults of existing
+#' arguments.
+#' @param penvir The environment used when searching for a future
+#' function by its name.
+#'
+#' @return a future function.
+#'
+#' @seealso
+#' Use \code{\link{plan}()} to set a future to become the
+#' new default strategy.
+#'
+#' @export
+tweak <- function(strategy, ..., penvir=parent.frame()) UseMethod("tweak")
+
+#' @export
+tweak.character <- function(strategy, ..., penvir=parent.frame()) {
+  ## Search attached packages and the 'future' package
+  ## for a future function with this name
+  envirs <- list(penvir, future=getNamespace("future"), NULL)
+  for (envir in envirs) {
+    ## Reached the end? Nothing found.
+    if (is.null(envir)) {
+      stop("No such strategy for futures: ", sQuote(strategy))
+    }
+
+    if (exists(strategy, mode="function", envir=envir, inherits=TRUE)) {
+      strategy <- get(strategy, mode="function", envir=envir, inherits=TRUE)
+      break
+    }
+  }
+
+  ## Sanity check
+  stopifnot(is.function(strategy))
+
+  tweak(strategy, ..., penvir=penvir)
+}
+
+#' @export
+tweak.future <- function(strategy, ..., penvir=parent.frame()) {
+  args <- list(...)
+
+  ## Nothing to tweak?
+  if (length(args) == 0L) return(strategy)
+
+  names <- names(args)
+  if (is.null(names)) {
+    stop("Additional arguments to tweak() must be named.")
+  }
+
+
+  ## formals()<- drops any attributes including class
+  attrs <- attributes(strategy)
+  class <- class(strategy)
+
+  ## Tweak arguments
+  formals <- names(formals(strategy))
+
+  ## BACKWARD COMPATIBILITY
+  for (name in c("maxCores", "cluster")) {
+    if (name %in% names) {
+      if ("workers" %in% formals) {
+        names <- gsub(name, "workers", names, fixed=TRUE)
+        names(args) <- names
+        .Deprecated(msg=sprintf("Argument '%s' has been renamed to 'workers'. Please update you script/code that uses the future package.", name))
+      }
+    }
+  }
+
+  unknown <- NULL
+  for (kk in seq_along(args)) {
+    name <- names[kk]
+    if (is.element(name, formals)) {
+      formals(strategy)[[name]] <- args[[name]]
+    } else {
+      unknown <- c(unknown, name)
+    }
+  }
+  if (length(unknown) > 0L) {
+    warning(sprintf("Ignored %d unknown arguments: %s", length(unknown), paste(sQuote(unknown), collapse=", ")))
+  }
+
+  ## Restore attributes including class
+  attributes(strategy) <- attrs
+
+  ## Flag that it is tweaked
+  class(strategy) <- c("tweaked", class)
+
+  strategy
+} ## tweak()
diff --git a/R/tweakExpression.R b/R/tweakExpression.R
new file mode 100644
index 0000000..c71b5b1
--- /dev/null
+++ b/R/tweakExpression.R
@@ -0,0 +1,27 @@
+tweakExpression <- function(expr) {
+  if (!is.language(expr)) return(expr)
+
+  for (ii in seq_along(expr)) {
+    # If expr[[ii]] is "missing", ignore the error.  This
+    # happens with for instance expressions like x[,1].
+    # FIXME: Is there a better way?!? /HB 2014-05-08
+    tryCatch({
+      exprI <- expr[[ii]]
+      op <- exprI[[1]]
+      if (!is.symbol(op)) next
+      op <- as.character(op)
+      if (op %in% c("<<-", "%<-%", "%<=%")) {
+        lhs <- exprI[[2]]
+        rhs <- exprI[[3]]
+        ## covr: skip=1
+        expr[[ii]] <- substitute({a <- b; e}, list(a=lhs, b=rhs, e=exprI))
+      } else if (op %in% c("->>", "%->%", "%=>%")) {
+        lhs <- exprI[[3]]
+        rhs <- exprI[[2]]
+        ## covr: skip=1
+        expr[[ii]] <- substitute({a <- b; e}, list(a=lhs, b=rhs, e=exprI))
+      }
+    }, error=function(ex) {})
+  }
+  expr
+} # tweakExpression()
diff --git a/R/tweak_OP.R b/R/tweak_OP.R
new file mode 100644
index 0000000..c56f20b
--- /dev/null
+++ b/R/tweak_OP.R
@@ -0,0 +1,29 @@
+#' Temporarily tweaks the arguments of the current strategy
+#'
+#' @usage fassignment \%tweak\% tweaks
+#'
+#' @param fassignment The future assignment, e.g.
+#'        \code{x \%<=\% \{ expr \}}.
+#' @param tweaks A named list (or vector) with arguments that
+#' should be changed relative to the current strategy.
+#'
+#' @export
+`%tweak%` <- function(fassignment, tweaks) {
+  fassignment <- substitute(fassignment)
+  envir <- parent.frame(1)
+  stopifnot(is.vector(tweaks))
+  tweaks <- as.list(tweaks)
+  stopifnot(!is.null(names(tweaks)))
+
+  ## Temporarily use a different plan
+  oplan <- plan("list")
+  on.exit(plan(oplan, substitute=FALSE, .call=NULL))
+
+  ## Tweak current strategy and apply
+  plans <- oplan
+  args <- c(list(plans[[1]], penvir=envir), tweaks)
+  plans[[1]] <- do.call(tweak, args=args)
+  plan(plans, substitute=FALSE, .call=NULL)
+
+  eval(fassignment, envir=envir)
+}
diff --git a/R/utils.R b/R/utils.R
new file mode 100644
index 0000000..a87360a
--- /dev/null
+++ b/R/utils.R
@@ -0,0 +1,378 @@
+## From R.utils 2.0.2 (2015-05-23)
+hpaste <- function(..., sep="", collapse=", ", lastCollapse=NULL, maxHead=if (missing(lastCollapse)) 3 else Inf, maxTail=if (is.finite(maxHead)) 1 else Inf, abbreviate="...") {
+  if (is.null(lastCollapse)) lastCollapse <- collapse
+
+  # Build vector 'x'
+  x <- paste(..., sep=sep)
+  n <- length(x)
+
+  # Nothing todo?
+  if (n == 0) return(x)
+  if (is.null(collapse)) return(x)
+
+  # Abbreviate?
+  if (n > maxHead + maxTail + 1) {
+    head <- x[seq_len(maxHead)]
+    tail <- rev(rev(x)[seq_len(maxTail)])
+    x <- c(head, abbreviate, tail)
+    n <- length(x)
+  }
+
+  if (!is.null(collapse) && n > 1) {
+    if (lastCollapse == collapse) {
+      x <- paste(x, collapse=collapse)
+    } else {
+      xT <- paste(x[1:(n-1)], collapse=collapse)
+      x <- paste(xT, x[n], sep=lastCollapse)
+    }
+  }
+
+  x
+} # hpaste()
+
+
+trim <- function(s) {
+  sub("[\t\n\f\r ]+$", "", sub("^[\t\n\f\r ]+", "", s))
+} # trim()
+
+
+hexpr <- function(expr, trim=TRUE, collapse="; ", maxHead=6L, maxTail=3L, ...) {
+  code <- deparse(expr)
+  if (trim) code <- trim(code)
+  hpaste(code, collapse=collapse, maxHead=maxHead, maxTail=maxTail, ...)
+} # hexpr()
+
+
+## From R.filesets
+asIEC <- function(size, digits=2L) {
+  if (length(size) > 1L) return(sapply(size, FUN=asIEC, digits=digits))
+  units <- c("bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB")
+  for (unit in units) {
+    if (size < 1000) break;
+    size <- size / 1024
+  }
+
+  if (unit == "bytes") {
+    fmt <- sprintf("%%.0f %s", unit)
+  } else {
+    fmt <- sprintf("%%.%df %s", digits, unit)
+  }
+  sprintf(fmt, size)
+} # asIEC()
+
+
+mdebug <- function(...) {
+  if (!getOption("future.debug", FALSE)) return()
+  message(sprintf(...))
+} ## mdebug()
+
+
+## A universally unique identifier (UUID) for the current
+## R process.  Generated only once.
+#' @importFrom digest digest
+uuid <- local({
+  value <- NULL
+  function() {
+    uuid <- value
+    if (!is.null(uuid)) return(uuid)
+    info <- Sys.info()
+    host <- Sys.getenv(c("HOST", "HOSTNAME", "COMPUTERNAME"))
+    host <- host[nzchar(host)][1]
+    info <- list(
+      host=host,
+      info=info,
+      pid=Sys.getpid(),
+      time=Sys.time(),
+      random=sample.int(.Machine$integer.max, size=1L)
+    )
+    uuid <- digest(info)
+    uuid <- strsplit(uuid, split="")[[1]]
+    uuid <- paste(c(uuid[1:8], "-", uuid[9:12], "-", uuid[13:16], "-", uuid[17:20], "-", uuid[21:32]), collapse="")
+    attr(uuid, "info") <- info
+    value <<- uuid
+    uuid
+  }
+})
+
+
+## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+## Used by run() for ClusterFuture.
+## - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+## Because these functions are exported, we want to keep their
+## environment() as small as possible, which is why we use local().
+## Without, the environment would be that of the package itself
+## and all of the package content would be exported.
+
+## Removes all variables in the global environment.
+grmall <- local(function(envir=.GlobalEnv) {
+  vars <- ls(envir=envir, all.names=TRUE)
+  rm(list=vars, envir=envir, inherits=FALSE)
+})
+
+## Assigns a value to the global environment.
+gassign <- local(function(name, value, envir=.GlobalEnv) {
+  assign(name, value=value, envir=envir)
+  NULL
+})
+
+## Evaluates an expression in global environment.
+geval <- local(function(expr, substitute=FALSE, envir=.GlobalEnv, ...) {
+  if (substitute) expr <- substitute(expr)
+  eval(expr, envir=envir)
+})
+
+## Vectorized version of require() with bells and whistles
+requirePackages <- local(function(pkgs) {
+  requirePackage <- function(pkg) {
+    if (require(pkg, character.only=TRUE)) return()
+
+    ## Failed to attach package
+    msg <- sprintf("Failed to attach package %s in %s", sQuote(pkg), R.version$version.string)
+    data <- utils::installed.packages()
+
+    ## Installed, but fails to load/attach?
+    if (is.element(pkg, data[,"Package"])) {
+      keep <- (data[,"Package"] == pkg)
+      data <- data[keep,,drop=FALSE]
+      pkgs <- sprintf("%s %s (in %s)", data[,"Package"], data[, "Version"], sQuote(data[,"LibPath"]))
+      msg <- sprintf("%s, although the package is installed: %s", msg, paste(pkgs, collapse=", "))
+    } else {
+      paths <- .libPaths()
+      msg <- sprintf("%s, because the package is not installed in any of the libraries (%s), which contain %d installed packages.", msg, paste(sQuote(paths), collapse=", "), nrow(data))
+    }
+
+    stop(msg)
+  } ## requirePackage()
+
+  ## require() all packages
+  pkgs <- unique(pkgs)
+  lapply(pkgs, FUN=requirePackage)
+}) ## requirePackages()
+
+
+## When 'default' is specified, this is 30x faster than
+## base::getOption().  The difference is that here we use
+## use names(.Options) whereas in 'base' names(options())
+## is used.
+getOption <- local({
+  go <- base::getOption
+  function(x, default=NULL) {
+    if (missing(default) || match(x, table=names(.Options), nomatch=0L) > 0L) go(x) else default
+  }
+}) ## getOption()
+
+
+detectCores <- local({
+  res <- NULL
+  function() {
+    if (is.null(res)) {
+      ## Get number of system cores from option, system environment,
+      ## and finally detectCores().  This also designed such that
+      ## it is indeed possible to return NA_integer_.
+      value <- getOption("future.availableCores.system")
+      if (!is.null(value)) {
+        value <- as.integer(value)
+	return(value)
+      }
+      
+      value <- parallel::detectCores()
+      
+      ## If unknown, set default to 1L
+      if (is.na(value)) value <- 1L
+      value <- as.integer(value)
+      
+      ## Assert positive integer
+      stopifnot(length(value) == 1L, is.numeric(value),
+                is.finite(value), value >= 1L)
+		
+      res <<- value
+    }
+    res
+  }
+})
+
+
+## We are currently importing the following non-exported functions:
+## * parallel:::defaultCluster()
+## * parallel:::recvResult()
+## * parallel:::selectChildren()
+## * parallel:::sendCall()
+## As well as the following ones (because they are not exported on Windows):
+## * parallel:::mccollect()
+## * parallel:::mcparallel()
+importParallel <- function(name=NULL) {
+  ns <- getNamespace("parallel")
+  if (!exists(name, mode="function", envir=ns, inherits=FALSE)) {
+    ## covr: skip=3
+    msg <- sprintf("This type of future processing is not supported on this system (%s), because parallel function %s() is not available", sQuote(.Platform$OS.type), name)
+    mdebug(msg)
+    stop(msg, call.=FALSE)
+  }
+  get(name, mode="function", envir=ns, inherits=FALSE)
+}
+
+
+parseCmdArgs <- function() {
+  cmdargs <- getOption("future.cmdargs", commandArgs())
+  args <- list()
+
+  ## Option --parallel=<n> or -p <n>
+  idx <- grep("^(-p|--parallel=.*)$", cmdargs)
+  if (length(idx) > 0) {
+    ## Use only last, iff multiple are given
+    if (length(idx) > 1) idx <- idx[length(idx)]
+
+    cmdarg <- cmdargs[idx]
+    if (cmdarg == "-p") {
+      cmdarg <- cmdargs[idx+1L]
+      value <- as.integer(cmdarg)
+      cmdarg <- sprintf("-p %s", cmdarg)
+    } else {
+      value <- as.integer(gsub("--parallel=", "", cmdarg))
+    }
+
+    max <- availableCores(methods="system")
+    if (is.na(value) || value <= 0L) {
+      msg <- sprintf("future: Ignoring invalid number of processes specified in command-line option: %s", cmdarg)
+      warning(msg, call.=FALSE, immediate.=TRUE)
+    } else if (value > max) {
+      msg <- sprintf("future: Ignoring requested number of processes, because it is greater than the number of cores/child processes available (=%d) to this R process: %s", max, cmdarg)
+      warning(msg, call.=FALSE, immediate.=TRUE)
+    } else {
+      args$p <- value
+    }
+  }
+
+  args
+} # parseCmdArgs()
+
+
+myExternalIP <- local({
+  ip <- NULL
+  function(force=FALSE, mustWork=TRUE) {
+    if (!force && !is.null(ip)) return(ip)
+    
+    ## FIXME: The identification of the external IP number relies on a
+    ## single third-party server.  This could be improved by falling back
+    ## to additional servers, cf. https://github.com/phoemur/ipgetter
+    urls <- c(
+      "https://myexternalip.com/raw",
+      "https://diagnostic.opendns.com/myip",
+      "https://api.ipify.org/",
+      "http://myexternalip.com/raw",
+      "http://diagnostic.opendns.com/myip",
+      "http://api.ipify.org/"
+    )
+    value <- NULL
+    for (url in urls) {
+      value <- tryCatch(readLines(url), error = function(ex) NULL)
+      if (!is.null(value)) break
+    }
+    
+    ## Nothing found?
+    if (is.null(value)) {
+      if (mustWork) {
+        stop(sprintf("Failed to identify external IP from any of the %d external services: %s", length(urls), paste(sQuote(urls), collapse=", ")))
+      }
+      return(NA_character_)
+    }
+
+    ## Trim and drop empty results (just in case)
+    value <- trim(value)
+    value <- value[nzchar(value)]
+
+    ## Nothing found?
+    if (length(value) == 0 && !mustWork) return(NA_character_)
+    
+    ## Sanity check
+    stopifnot(length(value) == 1, is.character(value), !is.na(value), nzchar(value))
+
+    ## Cache result
+    ip <<- value
+    
+    ip
+  }
+}) ## myExternalIP()
+
+
+myInternalIP <- local({
+  ip <- NULL
+
+  ## Known private network IPv4 ranges:
+  ##   (1)    10.0.0.0 -  10.255.255.255
+  ##   (2)  172.16.0.0 -  172.31.255.255
+  ##   (3) 192.168.0.0 - 192.168.255.255
+  ## https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
+  isPrivateIP <- function(ips) {
+    ips <- strsplit(ips, split=".", fixed=TRUE)
+    ips <- lapply(ips, FUN=as.integer)
+    res <- logical(length=length(ips))
+    for (kk in seq_along(ips)) {
+      ip <- ips[[kk]]
+      if (ip[1] == 10) {
+        res[kk] <- TRUE
+      } else if (ip[1] == 172) {
+        if (ip[2] >= 16 && ip[2] <= 31) res[kk] <- TRUE
+      } else if (ip[1] == 192) {
+        if (ip[2] == 168) res[kk] <- TRUE
+      }
+    }
+    res
+  } ## isPrivateIP()
+
+  function(force=FALSE, which=c("first", "last", "all"), mustWork=TRUE) {
+    if (!force && !is.null(ip)) return(ip)
+    which <- match.arg(which)
+
+    value <- NULL
+    os <- R.version$os
+    pattern <- "[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+"
+    if (grepl("^linux", os)) {
+      res <- system2("hostname", args="-I", stdout=TRUE)
+      res <- grep(pattern, res, value=TRUE)
+      res <- unlist(strsplit(res, split="[ ]+", fixed=FALSE))
+      res <- grep(pattern, res, value=TRUE)
+      res <- unique(trim(res))
+      ## Keep private network IPs only (just in case)
+      value <- res[isPrivateIP(res)]
+    } else if (grepl("^mingw", os)) {
+      res <- system2("ipconfig", stdout=TRUE)
+      res <- grep("IPv4", res, value=TRUE)
+      res <- grep(pattern, res, value=TRUE)
+      res <- unlist(strsplit(res, split="[ ]+", fixed=FALSE))
+      res <- grep(pattern, res, value=TRUE)
+      res <- unique(trim(res))
+      ## Keep private network IPs only (just in case)
+      value <- res[isPrivateIP(res)]
+    } else {
+      if (mustWork) {
+        stop(sprintf("remote(..., myip='<internal>') is yet not implemented for this operating system (%s). Please specify the 'myip' IP number manually.", os))
+      }
+      return(NA_character_)
+    }
+
+    ## Trim and drop empty results (just in case)
+    value <- trim(value)
+    value <- value[nzchar(value)]
+
+    ## Nothing found?
+    if (length(value) == 0 && !mustWork) return(NA_character_)
+
+    if (length(value) > 1) {
+      value <- switch(which,
+        first = value[1],
+        last  = value[length(value)],
+        all   = value,
+        value
+      )
+    }
+    ## Sanity check
+
+    stopifnot(is.character(value), length(value) >= 1, !any(is.na(value)))
+
+    ## Cache result
+    ip <<- value
+
+    ip
+  }
+}) ## myInternalIP()
diff --git a/R/values.R b/R/values.R
new file mode 100644
index 0000000..fbf31e3
--- /dev/null
+++ b/R/values.R
@@ -0,0 +1,56 @@
+#' Gets all values in an object
+#'
+#' Gets all values in an environment, a list, or a list environment
+#' and returns an object of the same class (and dimensions).
+#' All future elements are replaced by their corresponding
+#' \code{value()} values.  For all other elements, the existing
+#' object is kept.
+#'
+#' @param x An environment, a list, or a list environment.
+#' @param ... Additional arguments passed to \code{value()} of each future.
+#'
+#' @return An object of same type as \code{x} and with the same names
+#' and/or dimensions, if set.
+#'
+#' @export
+values <- function(x, ...) UseMethod("values")
+
+#' @export
+values.list <- function(x, ...) {
+  y <- futures(x)
+  y <- resolve(y)
+
+  for (ii in seq_along(y)) {
+    tmp <- y[[ii]]
+    if (inherits(tmp, "Future")) y[[ii]] <- value(tmp, ...)
+  }
+  y
+}
+
+#' @export
+values.environment <- function(x, ...) {
+  y <- futures(x)
+  y <- resolve(y)
+  names <- ls(envir=y, all.names=TRUE)
+  for (key in names) {
+    tmp <- y[[key]]
+    if (inherits(tmp, "Future")) y[[key]] <- value(tmp, ...)
+  }
+  y
+}
+
+#' @export
+values.listenv <- function(x, ...) {
+  y <- futures(x)
+  y <- resolve(y)
+  for (ii in seq_along(y)) {
+    tmp <- y[[ii]]
+    if (inherits(tmp, "Future")) y[[ii]] <- value(tmp, ...)
+  }
+  y
+}
+
+#' @export
+values.Future <- function(x, ...) {
+  value(x, ...)
+}
diff --git a/R/whichIndex.R b/R/whichIndex.R
new file mode 100644
index 0000000..4836ff1
--- /dev/null
+++ b/R/whichIndex.R
@@ -0,0 +1,61 @@
+whichIndex <- function(I, dim, dimnames=NULL) {
+  ndim <- length(dim)
+  stopifnot((is.matrix(I) || is.data.frame(I)), ncol(I) == ndim)
+  if (!is.null(dimnames)) stopifnot(length(dimnames) == ndim)
+  if (ndim == 0L) return(integer(0L))
+
+  if (is.data.frame(I)) {
+    ## Convert each column to indices
+    I2 <- array(NA_integer_, dim=dim(I))
+    for (kk in 1:ndim) {
+      idxs <- I[[kk]]
+      if (is.numeric(idxs)) {
+        if (any(idxs < 1 | idxs > dim[kk])) {
+          stop("Index out of range.")
+        }
+      } else {
+        idxs <- as.character(idxs)
+        idxs <- match(idxs, dimnames[[kk]])
+        if (anyNA(idxs)) {
+          unknown <- I[is.na(idxs),kk]
+          stop("Unknown indices: ", hpaste(sQuote(unknown)))
+        }
+      }
+      I2[,kk] <- idxs
+    }
+    I <- I2
+    I2 <- NULL
+  } else if (is.numeric(I)) {
+    for (kk in 1:ndim) {
+      idxs <- I[,kk]
+      if (any(idxs < 1 | idxs > dim[kk])) {
+        stop("Index out of range.")
+      }
+    }
+  } else {
+    ## Convert dimnames to dimindices
+    I2 <- array(NA_integer_, dim=dim(I))
+    for (kk in 1:ndim) {
+      ## Could be, say, factor
+      idxs <- I[,kk]
+      idxs <- as.character(idxs)
+      idxs <- match(idxs, dimnames[[kk]])
+      if (anyNA(idxs)) {
+        unknown <- I[is.na(idxs),kk]
+        stop("Unknown indices: ", hpaste(sQuote(unknown)))
+      }
+      I2[,kk] <- idxs
+    }
+    I <- I2
+    I2 <- NULL
+  }
+
+  ## Nothing more to do?
+  if (ndim == 1) return(I[,1L])
+
+  base <- cumprod(dim[-ndim])
+  for (kk in 2:ndim) {
+    I[,kk] <- (I[,kk]-1) * base[kk-1L]
+  }
+  rowSums(I)
+}
diff --git a/R/zzz.R b/R/zzz.R
new file mode 100644
index 0000000..2183499
--- /dev/null
+++ b/R/zzz.R
@@ -0,0 +1,98 @@
+## covr: skip=all
+.onLoad <- function(libname, pkgname) {
+  ## Unless already set, set option 'future.availableCores.system' according
+  ## to system environment variable 'R_FUTURE_AVAILABLECORES_SYSTEM'.
+  ncores <- getOption("future.availableCores.system")
+  if (is.null(ncores)) {
+    ncores <- trim(Sys.getenv("R_FUTURE_AVAILABLECORES_SYSTEM"))
+    if (nzchar(ncores)) {
+      mdebug("R_FUTURE_AVAILABLECORES_SYSTEM=%s", sQuote(ncores))
+      if (is.element(ncores, c("NA_integer_", "NA"))) {
+        ncores <- NA_integer_
+      } else {
+        ncores <- as.integer(ncores)
+      }
+      mdebug("=> options(future.availableCores.system=%d)", ncores)
+      options(future.availableCores.system=ncores)
+    }
+    ncores <- getOption("future.availableCores.system")
+  }
+  if (!is.null(ncores)) {
+    mdebug("Option 'future.availableCores.system=%d", ncores)
+  }
+
+  ## Unless already set, set option 'future.plan' according to
+  ## system environment variable 'R_FUTURE_PLAN'.
+  strategy <- getOption("future.plan")
+  if (is.null(strategy)) {
+    strategy <- trim(Sys.getenv("R_FUTURE_PLAN"))
+    if (nzchar(strategy)) {
+      mdebug("R_FUTURE_PLAN=%s", sQuote(strategy))
+      mdebug("=> options(future.plan='%s')", strategy)
+      options(future.plan=strategy)
+    }
+    strategy <- getOption("future.plan")
+  }
+  if (!is.null(strategy)) {
+    if (is.character(strategy)) {
+      mdebug("Option 'future.plan'=%s", sQuote(strategy))
+    } else {
+      mdebug("Option 'future.plan' of type %s", sQuote(mode(strategy)))
+    }
+  }
+
+  args <- parseCmdArgs()
+  p <- args$p
+  if (!is.null(p)) {
+    mdebug("R command-line argument: -p %s", p)
+    
+    ## Apply
+    options(mc.cores=p-1L)
+    ## options(Ncpus=p-1L) ## FIXME: Does it make sense? /HB 2016-04-02
+
+    ## Set 'future.plan' option?
+    if (!is.null(strategy)) {
+      mdebug("=> 'future.plan' already set.")
+    } else if (p == 1L) {
+      mdebug("=> options(future.plan=eager)")
+      options(future.plan=eager)
+    } else {
+      mdebug("=> options(future.plan=tweak(multiprocess, workers=%s))", p)
+      options(future.plan=tweak(multiprocess, workers=p))
+    }
+  }
+
+  ## Create UUID for this process
+  id <- uuid()
+  mdebug("R process uuid: %s", id)
+
+  mdebug("Setting plan('default')")
+  plan("default")
+} ## .onLoad()
+
+
+## covr: skip=all
+#' @importFrom utils file_test
+.onAttach <- function(libname, pkgname) {
+  ## Load .future.R script?
+  loadDotFuture <- getOption("future.startup.loadScript", TRUE)
+  if (isTRUE(loadDotFuture)) {
+    pathnames <- c(".future.R", "~/.future.R")
+    pathnames <- pathnames[file_test("-f", pathnames)]
+  
+    if (length(pathnames) == 0) {
+      mdebug("Future scripts identified: <none>")
+      return()
+    }
+    mdebug("Future scripts identified: %s", paste(sQuote(pathnames), collapse=", "))
+    pathname <- pathnames[1]
+    mdebug("Future script to load: %s", sQuote(pathname))
+    tryCatch({
+      source(pathname, chdir=FALSE, echo=FALSE, local=FALSE)
+    }, error = function(ex) {
+      msg <- sprintf("Failed to source %s file while attaching the future package. Will ignore this error, but please investigate. The error message was: %s", sQuote(pathname), sQuote(ex$message))
+      mdebug(msg)
+      warning(msg)
+    })
+  }
+} ## .onAttach()
diff --git a/build/vignette.rds b/build/vignette.rds
new file mode 100644
index 0000000..7405d6d
Binary files /dev/null and b/build/vignette.rds differ
diff --git a/demo/00Index b/demo/00Index
new file mode 100644
index 0000000..2103299
--- /dev/null
+++ b/demo/00Index
@@ -0,0 +1,4 @@
+fibonacci	Lazy definition of the first 100 Fibonacci numbers
+mandelbrot	Mandelbrot set images using futures
+
+
diff --git a/demo/fibonacci.R b/demo/fibonacci.R
new file mode 100644
index 0000000..d6a5e69
--- /dev/null
+++ b/demo/fibonacci.R
@@ -0,0 +1,30 @@
+library("future")
+library("listenv")
+
+## Defines the first 100 Fibonacci numbers
+## (0, 1, 1, 2, 3, 5, 8, ...)
+## but calculate only the ones need when
+## a number is actually requested.
+oplan <- plan(lazy)
+
+x <- listenv()
+x[[1]] <- 0
+x[[2]] <- 1
+for (i in 3:100) {
+  x[[i]] %<-% { x[[i-2]] + x[[i-1]] }
+}
+
+## At this point nothing has been calculated,
+## because lazy evaluation is in place.
+
+## Get the 7:th Fibonnaci numbers (should be 8)
+print(x[[7]])
+
+## At this point x[1:7] have been calculated,
+## but nothing beyond.
+
+## Let's get the 50:th number.
+print(x[[50]])
+
+## Reset plan
+plan(oplan)
diff --git a/demo/mandelbrot.R b/demo/mandelbrot.R
new file mode 100644
index 0000000..5561b42
--- /dev/null
+++ b/demo/mandelbrot.R
@@ -0,0 +1,94 @@
+library("future")
+library("graphics")
+
+plotWhatIsDone <- function(counts) {
+  for (kk in seq_along(counts)) {
+    f <- counts[[kk]]
+
+    ## Already plotted?
+    if (!inherits(f, "Future")) next
+
+    ## Not resolved?
+    if (!resolved(f)) next
+    
+    cat(sprintf("Plotting tile #%d of %d ...\n", kk, n))
+    counts[[kk]] <- value(counts[[kk]])
+    screen(kk)
+    plot(counts[[kk]])
+  } # for (kk ...)
+
+  counts
+} # plotWhatIsDone()
+
+
+## Options
+region <- getOption("future.demo.mandelbrot.region", 1L)
+if (!is.list(region)) {
+  if (region == 1L) {
+    region <- list(xmid=-0.75, ymid=0.0, side=3.0)
+  } else if (region == 2L) {
+    region <- list(xmid=0.283, ymid=-0.0095, side=0.00026)
+  } else if (region == 3L) {
+    region <- list(xmid=0.282989, ymid=-0.01, side=3e-8)
+  }
+}
+nrow <- getOption("future.demo.mandelbrot.nrow", 3L)
+delay <- getOption("future.demo.mandelbrot.delay", interactive())
+if (isTRUE(delay)) {
+  delay <- function(counts) Sys.sleep(rexp(1, rate=2))
+} else if (!is.function(delay)) {
+  delay <- function(counts) {}
+}
+
+## Generate Mandelbrot tiles to be computed
+Cs <- mandelbrotTiles(xmid=region$xmid, ymid=region$ymid,
+                      side=region$side, nrow=nrow)
+
+if (interactive()) {
+  dev.new()
+  plot.new()
+  split.screen(dim(Cs))
+  for (ii in seq_along(Cs)) {
+    screen(ii)
+    par(mar=c(0,0,0,0))
+    text(x=1/2, y=1/2, sprintf("Future #%d\nunresolved", ii), cex=2)
+  }
+} else {
+  split.screen(dim(Cs))
+}
+
+
+counts <- list()
+n <- length(Cs)
+for (ii in seq_len(n)) {
+  cat(sprintf("Mandelbrot tile #%d of %d ...\n", ii, n))
+  C <- Cs[[ii]]
+  
+  counts[[ii]] <- future({
+    cat(sprintf("Calculating tile #%d of %d ...\n", ii, n))
+    fit <- mandelbrot(C)
+    
+    ## Emulate slowness
+    delay(fit)
+    
+    cat(sprintf("Calculating tile #%d of %d ... done\n", ii, n))
+    fit
+  })
+
+  ## Plot tiles that are already resolved
+  counts <- plotWhatIsDone(counts)
+}
+
+
+## Plot remaining tiles
+repeat {
+  counts <- plotWhatIsDone(counts)
+  if (!any(sapply(counts, FUN=inherits, "Future"))) break
+}
+  
+
+
+close.screen()
+
+
+message("SUGGESTION: Try to rerun this demo after changing strategy for how futures are resolved, e.g. plan(multiprocess).\n")
diff --git a/inst/doc/future-1-overview.html b/inst/doc/future-1-overview.html
new file mode 100644
index 0000000..7c8374f
--- /dev/null
+++ b/inst/doc/future-1-overview.html
@@ -0,0 +1,881 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+<title>A Future for R: A Comprehensive Overview</title>
+
+<script type="text/javascript">
+window.onload = function() {
+  var imgs = document.getElementsByTagName('img'), i, img;
+  for (i = 0; i < imgs.length; i++) {
+    img = imgs[i];
+    // center an image if it is the only element of its parent
+    if (img.parentElement.childElementCount === 1)
+      img.parentElement.style.textAlign = 'center';
+  }
+};
+</script>
+
+<!-- Styles for R syntax highlighter -->
+<style type="text/css">
+   pre .operator,
+   pre .paren {
+     color: rgb(104, 118, 135)
+   }
+
+   pre .literal {
+     color: #990073
+   }
+
+   pre .number {
+     color: #099;
+   }
+
+   pre .comment {
+     color: #998;
+     font-style: italic
+   }
+
+   pre .keyword {
+     color: #900;
+     font-weight: bold
+   }
+
+   pre .identifier {
+     color: rgb(0, 0, 0);
+   }
+
+   pre .string {
+     color: #d14;
+   }
+</style>
+
+<!-- R syntax highlighter -->
+<script type="text/javascript">
+var hljs=new function(){function m(p){return p.replace(/&/gm,"&").replace(/</gm,"<")}function f(r,q,p){return RegExp(q,"m"+(r.cI?"i":"")+(p?"g":""))}function b(r){for(var p=0;p<r.childNodes.length;p++){var q=r.childNodes[p];if(q.nodeName=="CODE"){return q}if(!(q.nodeType==3&&q.nodeValue.match(/\s+/))){break}}}function h(t,s){var p="";for(var r=0;r<t.childNodes.length;r++){if(t.childNodes[r].nodeType==3){var q=t.childNodes[r].nodeValue;if(s){q=q.replace(/\n/g,"")}p+=q}else{if(t.chi [...]
+hljs.initHighlightingOnLoad();
+</script>
+
+
+
+<style type="text/css">
+body, td {
+   font-family: sans-serif;
+   background-color: white;
+   font-size: 13px;
+}
+
+body {
+  max-width: 800px;
+  margin: auto;
+  padding: 1em;
+  line-height: 20px;
+}
+
+tt, code, pre {
+   font-family: 'DejaVu Sans Mono', 'Droid Sans Mono', 'Lucida Console', Consolas, Monaco, monospace;
+}
+
+h1 {
+   font-size:2.2em;
+}
+
+h2 {
+   font-size:1.8em;
+}
+
+h3 {
+   font-size:1.4em;
+}
+
+h4 {
+   font-size:1.0em;
+}
+
+h5 {
+   font-size:0.9em;
+}
+
+h6 {
+   font-size:0.8em;
+}
+
+a:visited {
+   color: rgb(50%, 0%, 50%);
+}
+
+pre, img {
+  max-width: 100%;
+}
+pre {
+  overflow-x: auto;
+}
+pre code {
+   display: block; padding: 0.5em;
+}
+
+code {
+  font-size: 92%;
+  border: 1px solid #ccc;
+}
+
+code[class] {
+  background-color: #F8F8F8;
+}
+
+table, td, th {
+  border: none;
+}
+
+blockquote {
+   color:#666666;
+   margin:0;
+   padding-left: 1em;
+   border-left: 0.5em #EEE solid;
+}
+
+hr {
+   height: 0px;
+   border-bottom: none;
+   border-top-width: thin;
+   border-top-style: dotted;
+   border-top-color: #999999;
+}
+
+ at media print {
+   * {
+      background: transparent !important;
+      color: black !important;
+      filter:none !important;
+      -ms-filter: none !important;
+   }
+
+   body {
+      font-size:12pt;
+      max-width:100%;
+   }
+
+   a, a:visited {
+      text-decoration: underline;
+   }
+
+   hr {
+      visibility: hidden;
+      page-break-before: always;
+   }
+
+   pre, blockquote {
+      padding-right: 1em;
+      page-break-inside: avoid;
+   }
+
+   tr, img {
+      page-break-inside: avoid;
+   }
+
+   img {
+      max-width: 100% !important;
+   }
+
+   @page :left {
+      margin: 15mm 20mm 15mm 10mm;
+   }
+
+   @page :right {
+      margin: 15mm 10mm 15mm 20mm;
+   }
+
+   p, h2, h3 {
+      orphans: 3; widows: 3;
+   }
+
+   h2, h3 {
+      page-break-after: avoid;
+   }
+}
+</style>
+
+<meta name="keywords" content="R, package, vignette, future, promise, lazy evaluation, synchronous, asynchronous, parallel, cluster">
+<meta name="author" content="Henrik Bengtsson">
+
+</head>
+
+<body>
+<h1>A Future for R: A Comprehensive Overview</h1>
+
+<h2>Introduction</h2>
+
+<p>The purpose of the <a href="http://cran.r-project.org/package=future">future</a> package is to provide a very simple and uniform way of evaluating R expressions asynchronously using various resources available to the user.</p>
+
+<p>In programming, a <em>future</em> is an abstraction for a <em>value</em> that may be available at some point in the future.  The state of a future can either be <em>unresolved</em> or <em>resolved</em>.  As soon as it is resolved, the value is available instantaneously.  If the value is queried while the future is still unresolved, the current process is <em>blocked</em> until the future is resolved.  It is possible to check whether a future is resolved or not without blocking.  Exact [...]
+
+<p>Here is an example illustrating how the basics of futures work.  First, consider the following code snippet that uses plain R code:</p>
+
+<pre><code class="r">> v <- {
++   cat("Resolving...\n")
++   3.14
++ }
+Resolving...
+> v
+[1] 3.14
+</code></pre>
+
+<p>It works by assigning the value of an expression to variable <code>v</code> and we then print the value of <code>v</code>.  Moreover, when the expression for <code>v</code> is evaluated we also print a message.</p>
+
+<p>Here is the same code snippet modified to use futures instead:</p>
+
+<pre><code class="r">> library("future")
+> v %<-% {
++   cat("Resolving...\n")
++   3.14
++ }
+Resolving...
+> v
+[1] 3.14
+</code></pre>
+
+<p>The difference is in how <code>v</code> is constructed; with plain R we use <code><-</code> whereas with futures we use <code>%<-%</code>.</p>
+
+<p>So why are futures useful?  Because we can choose to evaluate the future expression in a separate R process asynchronously by simply switching settings as:</p>
+
+<pre><code class="r">> library("future")
+> plan(multiprocess)
+> v %<-% {
++   cat("Resolving...\n")
++   3.14
++ }
+> v
+[1] 3.14
+</code></pre>
+
+<p>With asynchronous futures, the current/main R process does <em>not</em> block, which means it is available for further processing while the futures are being resolved
+in separates processes running in the background.  In other words, futures provide a simple but yet powerful construct for parallel and / or distributed processing in R.</p>
+
+<p>Now, if you cannot be bothered to read all the nitty-gritty details about futures, but just want to try them out, then skip to the end to play with the Mandelbrot demo using both parallel and non-parallel evaluation.</p>
+
+<h2>Implicit or Explicit Futures</h2>
+
+<p>Futures can be created either <em>implicitly</em> or <em>explicitly</em>.  In the introductory example above we used <em>implicit futures</em> created via the <code>v %<-% { expr }</code> construct.  An alternative is <em>explicit futures</em> using the <code>f <- future({ expr })</code> and <code>v <- value(f)</code> constructs.  With these, our example could alternatively be written as:</p>
+
+<pre><code class="r">> library("future")
+> f <- future({
++   cat("Resolving...\n")
++   3.14
++ })
+Resolving...
+> v <- value(f)
+> v
+[1] 3.14
+</code></pre>
+
+<p>Either style of future construct works equally(*) well.  The implicit style is most similar to how regular R code is written.  In principle, all you have to do is to replace <code><-</code> with a <code>%<-%</code> to turn the assignment into a future assignment.  On the other hand, this simplicity can also be deceiving, particularly when asynchronous futures are being used.  In contrast, the explicit style makes it much clearer that futures are being used, which lowers the risk [...]
+
+<p>(*) There are cases where <code>%<-%</code> cannot be used without some (small) modifications.  We will return to this in Section 'Constraints when using Implicit Futures' near the end of this document.</p>
+
+<p>To summarize, for explicit futures, we use:</p>
+
+<ul>
+<li><code>f <- future({ expr })</code> - creates a future</li>
+<li><code>v <- value(f)</code> - gets the value of the future (blocks if not yet resolved)</li>
+</ul>
+
+<p>For implicit futures, we use:</p>
+
+<ul>
+<li><code>v %<-% { expr }</code> - creates a future and a promise to its value</li>
+</ul>
+
+<p>To keep it simple, we will use the implicit style in the rest of this document, but everything discussed will also apply to explicit futures.</p>
+
+<h2>Controlling How Futures are Resolved</h2>
+
+<p>The future package implements the following types of futures:</p>
+
+<table><thead>
+<tr>
+<th align="left">Name</th>
+<th align="left">OSes</th>
+<th align="left">Description</th>
+</tr>
+</thead><tbody>
+<tr>
+<td align="left"><em>synchronous:</em></td>
+<td align="left"></td>
+<td align="left"><em>non-parallel:</em></td>
+</tr>
+<tr>
+<td align="left"><code>eager</code></td>
+<td align="left">all</td>
+<td align="left"></td>
+</tr>
+<tr>
+<td align="left"><code>lazy</code></td>
+<td align="left">all</td>
+<td align="left">lazy evaluation - happens only if the value is requested</td>
+</tr>
+<tr>
+<td align="left"><code>transparent</code></td>
+<td align="left">all</td>
+<td align="left">for debugging (eager w/ early signaling and w/out local)</td>
+</tr>
+<tr>
+<td align="left"><em>asynchronous:</em></td>
+<td align="left"></td>
+<td align="left"><em>parallel</em>:</td>
+</tr>
+<tr>
+<td align="left"><code>multiprocess</code></td>
+<td align="left">all</td>
+<td align="left">multicore iff supported, otherwise multisession</td>
+</tr>
+<tr>
+<td align="left"><code>multisession</code></td>
+<td align="left">all</td>
+<td align="left">background R sessions (on current machine)</td>
+</tr>
+<tr>
+<td align="left"><code>multicore</code></td>
+<td align="left">not Windows</td>
+<td align="left">forked R processes (on current machine)</td>
+</tr>
+<tr>
+<td align="left"><code>cluster</code></td>
+<td align="left">all</td>
+<td align="left">external R sessions on current, local, and/or remote machines</td>
+</tr>
+<tr>
+<td align="left"><code>remote</code></td>
+<td align="left">all</td>
+<td align="left">Simple access to remote R sessions</td>
+</tr>
+</tbody></table>
+
+<p>The future package is designed such that support for additional strategies can be implemented as well.  For instance, the <a href="https://github.com/HenrikBengtsson/future.BatchJobs">future.BatchJobs</a> package provides futures for all types of <em>cluster functions</em> (“backends”) that the <a href="http://cran.r-project.org/package=BatchJobs">BatchJobs</a> package supports.  Specifically, futures for evaluating R expressions via job schedulers such as Slurm, TORQUE/PB [...]
+
+<p>By default, future expressions are evaluated instantaneously and synchronously (in the current R session).  This evaluation strategy is referred to as “eager” and we refer to futures using this strategy as “eager futures”.  In this section, we will go through each of these strategies and discuss what they have in common and how they differ.</p>
+
+<h3>Consistent Behavior Across Futures</h3>
+
+<p>Before going through each of the different future strategies, it is probably helpful to clarify the objectives the Future API (as defined by the future package).  When programming with futures, it should not really matter what future strategy is used for executing code.  This is because we cannot really know what computational resources the user has access to so the choice of evaluation strategy should be in the hand of the user and not the developer.  In other words, the code should  [...]
+
+<p>One of the designs of the Future API was to encapsulate any differences such that all types of futures will appear to work the same.  This despite expressions may be evaluated locally in the current R session or across the world in remote R sessions.  Another obvious advantage of having a consistent API and behavior among different types of futures is that it helps while prototyping.  Typically one would use eager evaluation while building up a script and, later, when the script is fu [...]
+
+<p>Because of this, the defaults of the different strategies are such that the results and side effects of evaluating a future expression are as similar as possible.  More specifically, the following is true for all futures:</p>
+
+<ul>
+<li><p>All <em>evaluation is done in a local environment</em> (i.e. <code>local({ expr })</code>) such assignments do not affect the calling environment.  This is natural when evaluating in an external R process, but is also enforced when evaluating in the current R session.</p></li>
+<li><p>When a future is constructed, <em>global variables are identified</em>.  For asynchronous evaluation, globals are exported to the R process/session that will be evaluating the future expression.  For lazy futures, globals are “frozen” (cloned to a local environment of the future).  Also, in order to protect against exporting too large objects by mistake, there is a built-in assertion that the total size of all globals is less than a given threshold (controllable via an [...]
+<li><p>Future <em>expressions are only evaluated once</em>.  As soon as the value (or an error) has been collected it will be available for all succeeding requests.</p></li>
+</ul>
+
+<p>Here is an example illustrating that all assignments are done to a local environment:</p>
+
+<pre><code class="r">> plan(eager)
+> a <- 1
+> x %<-% {
++     a <- 2
++     2 * a
++ }
+> x
+[1] 4
+> a
+[1] 1
+</code></pre>
+
+<p>Now we are ready to explore the different future strategies.</p>
+
+<h3>Synchronous Futures</h3>
+
+<p>Synchronous futures are resolved one after another and most commonly by the R process that creates them.  When a synchronous future is being resolved it blocks the main process until resolved.  There are two main types of synchronous futures in the future package, <em>eager</em> and <em>lazy</em> futures, which are described next.</p>
+
+<h4>Eager Futures</h4>
+
+<p>Eager futures are the default unless otherwise specified.  They were designed to behave as similar as possible to regular R evaluation while still fulfilling the Future API and its behaviors.  Here is an example illustrating their properties:</p>
+
+<pre><code class="r">> plan(eager)
+> pid <- Sys.getpid()
+> pid
+[1] 31757
+> a %<-% {
++     pid <- Sys.getpid()
++     cat("Resolving 'a' ...\n")
++     3.14
++ }
+Resolving 'a' ...
+> b %<-% {
++     rm(pid)
++     cat("Resolving 'b' ...\n")
++     Sys.getpid()
++ }
+Resolving 'b' ...
+> c %<-% {
++     cat("Resolving 'c' ...\n")
++     2 * a
++ }
+Resolving 'c' ...
+> b
+[1] 31757
+> c
+[1] 6.28
+> a
+[1] 3.14
+> pid
+[1] 31757
+</code></pre>
+
+<p>Since eager evaluation is taking place, each of the three futures is resolved instantaneously in the moment it is created.  Note also how <code>pid</code> in the calling environment, which was assigned the process ID of the current process, is neither overwritten nor removed.  This is because futures are evaluated in a local environment.  Since synchronous (uni-)processing is used, future <code>b</code> is resolved by the main R process (still in a local environment), which is why the [...]
+
+<h4>Lazy Futures</h4>
+
+<p>A lazy future evaluates its expression only if its value is queried.  Evaluation can also be triggered when the future is checked for being resolved or not.  Here is the above example when using lazy evaluation:</p>
+
+<pre><code class="r">> plan(lazy)
+> pid <- Sys.getpid()
+> pid
+[1] 31757
+> a %<-% {
++     pid <- Sys.getpid()
++     cat("Resolving 'a' ...\n")
++     3.14
++ }
+> b %<-% {
++     rm(pid)
++     cat("Resolving 'b' ...\n")
++     Sys.getpid()
++ }
+> c %<-% {
++     cat("Resolving 'c' ...\n")
++     2 * a
++ }
+Resolving 'a' ...
+> b
+Resolving 'b' ...
+[1] 31757
+> c
+Resolving 'c' ...
+[1] 6.28
+> a
+[1] 3.14
+> pid
+[1] 31757
+</code></pre>
+
+<p>As previously, variable <code>pid</code> is unaffected because all evaluation is done in a local environment.  More interestingly, future <code>a</code> is no longer evaluated in the moment it is created, but instead when it is needed the first time, which happens when future <code>c</code> is created.  This is because <code>a</code> is identified as a global variable that needs to be captured (“frozen” to <code>a == 3.14</code>) in order to set up future <code>c</code>.   [...]
+
+<p><em>Comment</em>: Lazy evaluation is already used by R itself.  Arguments are passed to functions using lazy evaluation.  It is also possible to assign variables using lazy evaluation using <code>delayedAssign()</code>, but contrary to lazy futures this function does not freeze globals.  For more information, see <code>help("delayedAssign", package="base")</code>.</p>
+
+<h3>Asynchronous Futures</h3>
+
+<p>Next, we will turn to asynchronous futures, which are futures that are resolved in the background.  By design, these futures are non-blocking, that is, after being created the calling process is available for other tasks including creating additional futures.  It is only when the calling process tries to access the value of a future that is not yet resolved, or trying to create another asynchronous future when all available R processes are busy serving other futures, that it blocks.</p>
+
+<h4>Multisession Futures</h4>
+
+<p>We start with multisession futures because they are supported by all operating systems.  A multisession future is evaluated in a background R session running on the same machine as the calling R process.  Here is our example with multisession evaluation:</p>
+
+<pre><code class="r">> plan(multisession)
+> pid <- Sys.getpid()
+> pid
+[1] 31757
+> a %<-% {
++     pid <- Sys.getpid()
++     cat("Resolving 'a' ...\n")
++     3.14
++ }
+> b %<-% {
++     rm(pid)
++     cat("Resolving 'b' ...\n")
++     Sys.getpid()
++ }
+> c %<-% {
++     cat("Resolving 'c' ...\n")
++     2 * a
++ }
+> b
+[1] 31780
+> c
+[1] 6.28
+> a
+[1] 3.14
+> pid
+[1] 31757
+</code></pre>
+
+<p>The first thing we observe is that the values of <code>a</code>, <code>c</code> and <code>pid</code> are the same as previously.  However, we notice that <code>b</code> is different from before.  This is because future <code>b</code> is evaluated in a different R process and therefore it returns a different process ID.  Another difference is that the messages, generated by <code>cat()</code>, are no longer displayed.  This is because they are outputted to the background sessions and n [...]
+
+<p>When multisession evaluation is used, the package launches a set of R sessions in the background that will serve multisession futures by evaluating their expressions as they are created.  If all background sessions are busy serving other futures, the creation of the next multisession future is <em>blocked</em> until a background session becomes available again.  The total number of background processes launched is decided by the value of <code>availableCores()</code>, e.g.</p>
+
+<pre><code class="r">> availableCores()
+mc.cores+1 
+         3 
+</code></pre>
+
+<p>This particular result tells us that the <code>mc.cores</code> option was set such that we are allowed to use in total 3 processes including the main process.  In other words, with these settings, there will be 2 background processes serving the multisession futures.  The <code>availableCores()</code> is also agile to different options and system environment variables.  For instance, if compute cluster schedulers are used (e.g. TORQUE/PBS and Slurm), they set specific environment vari [...]
+
+<h4>Multicore Futures</h4>
+
+<p>On operating systems where R supports <em>forking</em> of processes, which is basically all operating system except Windows, an alternative to spawning R sessions in the background is to fork the existing R process.  Forking an R process is considered faster than working with a separate R session running in the background.  One reason is that the overhead of exporting large globals to the background session can be greater than when forking is used.
+To use multicore futures, we specify:</p>
+
+<pre><code class="r">plan(multicore)
+</code></pre>
+
+<p>The only real different between using multicore and multisession futures is that any output written (to standard output or standard error) by a multicore process is instantaneously outputted in calling process.  Other than this, the behavior of using multicore evaluation is very similar to that of using multisession evaluation.</p>
+
+<p>Just like for multisession futures, the maximum number of parallel processes running will be decided by <code>availableCores()</code>, since in both cases the evaluation is done on the local machine.</p>
+
+<h4>Multiprocess Futures</h4>
+
+<p>Sometimes we do not know whether multicore futures are supported or not, but it might still be that we would like to write platform-independent scripts or instructions that work everywhere.  In such cases we can specify that we want to use “multiprocess” futures as in:</p>
+
+<pre><code class="r">plan(multiprocess)
+</code></pre>
+
+<p>A multiprocess future is not a formal class of futures by itself, but rather a convenient alias for either of the two.  When this is specified, multisession evaluation will be used unless multicore evaluation is supported.</p>
+
+<h4>Cluster Futures</h4>
+
+<p>Cluster futures evaluate expressions on an ad-hoc cluster (as implemented by the parallel package).  For instance, assume you have access to three nodes <code>n1</code>, <code>n2</code> and <code>n3</code>, you can then use these for asynchronous evaluation as:</p>
+
+<pre><code class="r">> plan(cluster, workers = c("n1", "n2", "n3"))
+> pid <- Sys.getpid()
+> pid
+[1] 31757
+> a %<-% {
++     pid <- Sys.getpid()
++     cat("Resolving 'a' ...\n")
++     3.14
++ }
+> b %<-% {
++     rm(pid)
++     cat("Resolving 'b' ...\n")
++     Sys.getpid()
++ }
+> c %<-% {
++     cat("Resolving 'c' ...\n")
++     2 * a
++ }
+> b
+[1] 31802
+> c
+[1] 6.28
+> a
+[1] 3.14
+> pid
+[1] 31757
+</code></pre>
+
+<p>Just as for the other asynchronous evaluation strategies, the output from <code>cat()</code> is not displayed on the current/calling machine.</p>
+
+<p>Any types of clusters that <code>parallel::makeCluster()</code> creates can be used for cluster futures.  For instance, the above cluster can be explicitly set up as:</p>
+
+<pre><code class="r">cl <- parallel::makeCluster(c("n1", "n2", "n3"))
+plan(cluster, workers=cl)
+</code></pre>
+
+<p>Also, it is considered good style to shut down the cluster when it is no longer needed, that is, calling <code>parallel::stopCluster(cl)</code>.  However, it will shut itself down if the main process is terminated, which will happen in the first example where the cluster in created internally.  For more information on how to set up and manage such clusters, see <code>help("makeCluster", package="parallel")</code>.</p>
+
+<p>Note that with proper firewall and router configurations (e.g. port forwarding) and with automatic authentication setup (e.g. SSH key pairs), there is nothing preventing us from using the same approach for using a cluster of remote machines.</p>
+
+<h3>Different Strategies for Different Futures</h3>
+
+<p>Sometimes one may want to use an alternative evaluation strategy for a specific future.  Although one can use <code>old <- plan(new)</code> and afterward <code>plan(old)</code> to temporarily switch strategies, a simpler approach is to use the <code>%plan%</code> operator, e.g.</p>
+
+<pre><code class="r">> plan(eager)
+> pid <- Sys.getpid()
+> pid
+[1] 31757
+> a %<-% {
++     Sys.getpid()
++ }
+> b %<-% {
++     Sys.getpid()
++ } %plan% multiprocess
+> c %<-% {
++     Sys.getpid()
++ } %plan% multiprocess
+> a
+[1] 31757
+> b
+[1] 31819
+> c
+[1] 31820
+</code></pre>
+
+<p>As seen by the different process IDs, future <code>a</code> is evaluated eagerly using the same process as the calling environment whereas the other two are evaluated using multiprocess futures.</p>
+
+<p>However, using different plans to individual futures this way has the drawback of hard coding the evaluation strategy.  Doing so may prevent some users from using your script or your package, because they do not have the sufficient resources.  It may also prevent users with a lot of resources from utilizing those because you assumed a less-powerful set of hardware.  Because of this, we recommend against the use of <code>%plan%</code> other than for interactive prototyping.</p>
+
+<h3>Nested Futures and Evaluation Topologies</h3>
+
+<p>This far we have discussed what can be referred to as “flat topology” of futures, that is, all futures are created in and assigned to the same environment.  However, there is nothing stopping us from using a “nested topology” of futures, where one set of futures may, in turn, create another set of futures internally and so on.</p>
+
+<p>For instance, here is an example of two “top” futures (<code>a</code> and <code>b</code>) that uses multiprocess evaluation and where the second future (<code>b</code>) in turn uses two internal futures:</p>
+
+<pre><code class="r">> plan(multiprocess)
+> pid <- Sys.getpid()
+> a %<-% {
++     cat("Resolving 'a' ...\n")
++     Sys.getpid()
++ }
+> b %<-% {
++     cat("Resolving 'b' ...\n")
++     b1 %<-% {
++         cat("Resolving 'b1' ...\n")
++         Sys.getpid()
++     }
++     b2 %<-% {
++         cat("Resolving 'b2' ...\n")
++         Sys.getpid()
++     }
++     c(b.pid = Sys.getpid(), b1.pid = b1, b2.pid = b2)
++ }
+> pid
+[1] 31757
+> a
+[1] 31821
+> b
+ b.pid b1.pid b2.pid 
+ 31822  31822  31822 
+</code></pre>
+
+<p>By inspection the process IDs, we see that there are in total three different processes involved for resolving the futures.  There is the main R process (pid 31757), and there are the two processes used by <code>a</code> (pid 31821) and <code>b</code> (pid 31822).  However, the two futures (<code>b1</code> and <code>b2</code>) that is nested by <code>b</code> are evaluated by the same R process as <code>b</code>.  This is because nested futures use eager evaluation unless otherwise sp [...]
+
+<p>To specify a different type of <em>evaluation topology</em>, other than the first level of futures being resolved by multiprocess evaluation and the second level by eager evaluation, we can provide a list of evaluation strategies to <code>plan()</code>.  First, the same evaluation strategies as above can be explicitly specified as:</p>
+
+<pre><code class="r">plan(list(multiprocess, eager))
+</code></pre>
+
+<p>We would actually get the same behavior if we try with multiple levels of multiprocess evaluations;</p>
+
+<pre><code class="r">> plan(list(multiprocess, multiprocess))
+[...]
+> pid
+[1] 31757
+> a
+[1] 31823
+> b
+ b.pid b1.pid b2.pid 
+ 31824  31824  31824 
+</code></pre>
+
+<p>The reason for this is, also here, to protect us from launching more processes than what the machine can support.  Internally, this is done by setting <code>mc.cores</code> to zero (<a href="https://github.com/HenrikBengtsson/Wishlist-for-R/issues/7">sic!</a>) such that no <em>additional</em> parallel processes can be launched.  This is the case for both multisession and multicore evaluation.</p>
+
+<p>Continuing, if we start off by eager evaluation and then use multiprocess evaluation for any nested futures, we get:</p>
+
+<pre><code class="r">> plan(list(eager, multiprocess))
+[...]
+Resolving 'a' ...
+Resolving 'b' ...
+> pid
+[1] 31757
+> a
+[1] 31757
+> b
+ b.pid b1.pid b2.pid 
+ 31757  31825  31826 
+</code></pre>
+
+<p>which clearly show that <code>a</code> and <code>b</code> are resolved in the calling process (pid 31757) whereas the two nested futures (<code>b1</code> and <code>b2</code>) are resolved in two separate R processes (pids 31825 and 31826).</p>
+
+<p>Having said this, it is indeed possible to use nested multiprocess evaluation strategies, if we explicitly specify (read <em>force</em>) the number of cores available at each level.  In order to do this we need to “tweak” the default settings, which can be done as follows:</p>
+
+<pre><code class="r">> plan(list(tweak(multiprocess, workers = 3), tweak(multiprocess, 
++     workers = 3)))
+[...]
+> pid
+[1] 31757
+> a
+[1] 31827
+> b
+ b.pid b1.pid b2.pid 
+ 31828  31829  31834 
+</code></pre>
+
+<p>First, we see that both <code>a</code> and <code>b</code> are resolved in different processes (pids 31827 and 31828) than the calling process (pid 31757).  Second, the two nested futures (<code>b1</code> and <code>b2</code>) are resolved in yet two other R processes (pids 31829 and 31834).</p>
+
+<p>To clarify, when we set up the two levels of multiprocess evaluation, we specified that in total 3 processes may be used at each level.  We choose three parallel processes, not just two, because one is always consumed by the calling process leaving two to be used for the asynchronous futures.  This is why we see that <code>pid</code>, <code>a</code> and <code>b</code> are all resolved by the same process.  If we had allowed only two cores at the top level, <code>a</code> and <code>b</ [...]
+
+<p>For more details on working with nested futures and different evaluation strategies at each level, see Vignette '<a href="future-3-topologies.html">Futures in R: Future Topologies</a>'.</p>
+
+<h3>Checking A Future without Blocking</h3>
+
+<p>It is possible to check whether a future has been resolved or not without blocking.  This can be done using the <code>resolved(f)</code> function, which takes an explicit future <code>f</code> as input.  If we work with implicit futures (as in all the examples above), we can use the <code>f <- futureOf(a)</code> function to retrieve the explicit future from an implicit one.  For example,</p>
+
+<pre><code class="r">> plan(multiprocess)
+> a %<-% {
++     cat("Resolving 'a' ...")
++     Sys.sleep(2)
++     cat("done\n")
++     Sys.getpid()
++ }
+> cat("Waiting for 'a' to be resolved ...\n")
+Waiting for 'a' to be resolved ...
+> f <- futureOf(a)
+> count <- 1
+> while (!resolved(f)) {
++     cat(count, "\n")
++     Sys.sleep(0.2)
++     count <- count + 1
++ }
+1 
+2 
+3 
+4 
+5 
+> cat("Waiting for 'a' to be resolved ... DONE\n")
+Waiting for 'a' to be resolved ... DONE
+> a
+[1] 31835
+</code></pre>
+
+<h2>Failed Futures</h2>
+
+<p>Sometimes the future is not what you expected.  If an error occurs while evaluating a future, the error is propagated and thrown as an error in the calling environment <em>when the future value is requested</em>.  For example,</p>
+
+<pre><code class="r">> plan(lazy)
+> a %<-% {
++     cat("Resolving 'a' ...\n")
++     stop("Whoops!")
++     42
++ }
+> cat("Everything is still ok although we have created a future that will fail.\n")
+Everything is still ok although we have created a future that will fail.
+> a
+Resolving 'a' ...
+Error in eval(expr, envir, enclos) : Whoops!
+</code></pre>
+
+<p>The error is thrown each time the value is requested, that is, if we try to get the value again will generate the same error:</p>
+
+<pre><code class="r">> a
+Error in eval(expr, envir, enclos) : Whoops!
+In addition: Warning message:
+restarting interrupted promise evaluation
+</code></pre>
+
+<p>To see the list of calls (evaluated expressions) that lead up to the error, we can use the <code>backtrace()</code> function(*) on the future, i.e.</p>
+
+<pre><code class="r">> backtrace(a)
+[[1]]
+eval(quote({
+    cat("Resolving 'a' ...\n")
+    stop("Whoops!")
+    42
+}), new.env())
+[[2]]
+eval(expr, envir, enclos)
+[[3]]
+stop("Whoops!")
+</code></pre>
+
+<p>(*) The commonly used <code>traceback()</code> does not provide relevant information in the context of futures.</p>
+
+<h2>Globals</h2>
+
+<p>Whenever an R expression is to be evaluated asynchronously (in parallel) or via lazy evaluation, global objects have to be identified and passed to the evaluator.  They need to be passed exactly as they were at the time the future was created, because, for a lazy future, globals may otherwise change between when it is created and when it is resolved.  For asynchronous processing, the reason globals need to be identified is so that they can be exported to the process that evaluates the [...]
+
+<p>The future package tries to automate these tasks as far as possible.  It does this with help of the <a href="http://cran.r-project.org/package=globals">globals</a> package.  If a global variable is identified, it is captured and made available to the evaluating process.
+Moreover, if a global is defined in a package, then that global is not exported.  Instead, it is made sure that the corresponding package is attached when the future is evaluated.  This not only better reflects the setup of the main R session, but it also minimizes the need for exporting globals, which saves not only memory but also time and bandwidth, especially when using remote compute nodes.</p>
+
+<p>Finally, it should be clarified that identifying globals from static code inspection alone is a challenging problem.  There will always be corner cases where automatic identification of globals fails so that either false globals are identified (less of a concern) or some of the true globals are missing (which will result in a runtime error or possibly the wrong results).  Vignette '<a href="future-2-issues.html">Futures in R: Common Issues with Solutions</a>' provides examples [...]
+
+<h2>Constraints when using Implicit Futures</h2>
+
+<p>There is one limitation with implicit futures that does not exist for explicit ones.  Because an explicit future is just like any other object in R it can be assigned anywhere/to anything.  For instance, we can create several of them in a loop and assign them to a list, e.g.</p>
+
+<pre><code class="r">> plan(multiprocess)
+> f <- list()
+> for (ii in 1:3) {
++     f[[ii]] <- future({
++         Sys.getpid()
++     })
++ }
+> v <- lapply(f, FUN = value)
+> str(v)
+List of 3
+ $ : int 31838
+ $ : int 31839
+ $ : int 31840
+</code></pre>
+
+<p>This is <em>not</em> possible to do when using implicit futures.  This is because the <code>%<-%</code> assignment operator <em>cannot</em> be used in all cases where the regular <code><-</code> assignment operator can be used.  It can only be used to assign future values to <em>environments</em> (including the calling environment) much like how <code>assign(name, value, envir)</code> works.  However, we can assign implicit futures to environments using <em>named indices</em>, e.g.</p>
+
+<pre><code class="r">> plan(multiprocess)
+> v <- new.env()
+> for (name in c("a", "b", "c")) {
++     v[[name]] %<-% {
++         Sys.getpid()
++     }
++ }
+> v <- as.list(v)
+> str(v)
+List of 3
+ $ a: int 31841
+ $ b: int 31842
+ $ c: int 31844
+</code></pre>
+
+<p>Here <code>as.list(v)</code> blocks until all futures in the environment <code>v</code> have been resolved.  Then their values are collected and returned as a regular list.</p>
+
+<p>If <em>numeric indices</em> are required, then <em>list environments</em> can be used.  List environments, which are implemented by the <a href="http://cran.r-project.org/package=listenv">listenv</a> package, are regular environments with customized subsetting operators making it possible to index them much like how lists can be indexed.  By using list environments where we otherwise would use lists, we can also assign implicit futures to list-like objects using numeric indices.  For  [...]
+
+<pre><code class="r">> library("listenv")
+> plan(multiprocess)
+> v <- listenv()
+> for (ii in 1:3) {
++     v[[ii]] %<-% {
++         Sys.getpid()
++     }
++ }
+> v <- as.list(v)
+> str(v)
+List of 3
+ $ : int 31845
+ $ : int 31846
+ $ : int 31847
+</code></pre>
+
+<p>As previously, <code>as.list(v)</code> blocks until all futures are resolved.</p>
+
+<h2>Demos</h2>
+
+<p>To see a live illustration how different types of futures are evaluated, run the Mandelbrot demo of this package.  First, try with the eager evaluation,</p>
+
+<pre><code class="r">library("future")
+plan(eager)
+demo("mandelbrot", package="future", ask=FALSE)
+</code></pre>
+
+<p>which closely imitates how the script would run if futures were not used.  Then try the same using lazy evaluation,</p>
+
+<pre><code class="r">plan(lazy)
+demo("mandelbrot", package="future", ask=FALSE)
+</code></pre>
+
+<p>and see if you can notice the difference in how and when statements are evaluated.
+You may also try multiprocess evaluation, which calculates the different Mandelbrot planes using parallel R processes running in the background.  Try,</p>
+
+<pre><code class="r">plan(multiprocess)
+demo("mandelbrot", package="future", ask=FALSE)
+</code></pre>
+
+<p>This will use multicore processing if you are on a system where R supports process forking, otherwise (such as on Windows) it will use multisession processing.</p>
+
+<p>Finally, if you have access to multiple machines you can try to set up a cluster of workers and use them, e.g.</p>
+
+<pre><code class="r">plan(cluster, workers=c("n2", "n5", "n6", "n6", "n9"))
+demo("mandelbrot", package="future", ask=FALSE)
+</code></pre>
+
+<h2>Contributing</h2>
+
+<p>The goal of this package is to provide a standardized and unified API for using futures in R.  What you are seeing right now is an early but sincere attempt to achieve this goal.  If you have comments or ideas on how to improve the 'future' package, I would love to hear about them.  The preferred way to get in touch is via the <a href="https://github.com/HenrikBengtsson/future/">GitHub repository</a>, where you also find the latest source code.  I am also open to contributions [...]
+
+<hr/>
+
+<p>Copyright Henrik Bengtsson, 2015-2016</p>
+
+</body>
+
+</html>
diff --git a/inst/doc/future-2-issues.html b/inst/doc/future-2-issues.html
new file mode 100644
index 0000000..1a2aff3
--- /dev/null
+++ b/inst/doc/future-2-issues.html
@@ -0,0 +1,447 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+<title>A Future for R: Common Issues with Solutions</title>
+
+<script type="text/javascript">
+window.onload = function() {
+  var imgs = document.getElementsByTagName('img'), i, img;
+  for (i = 0; i < imgs.length; i++) {
+    img = imgs[i];
+    // center an image if it is the only element of its parent
+    if (img.parentElement.childElementCount === 1)
+      img.parentElement.style.textAlign = 'center';
+  }
+};
+</script>
+
+<!-- Styles for R syntax highlighter -->
+<style type="text/css">
+   pre .operator,
+   pre .paren {
+     color: rgb(104, 118, 135)
+   }
+
+   pre .literal {
+     color: #990073
+   }
+
+   pre .number {
+     color: #099;
+   }
+
+   pre .comment {
+     color: #998;
+     font-style: italic
+   }
+
+   pre .keyword {
+     color: #900;
+     font-weight: bold
+   }
+
+   pre .identifier {
+     color: rgb(0, 0, 0);
+   }
+
+   pre .string {
+     color: #d14;
+   }
+</style>
+
+<!-- R syntax highlighter -->
+<script type="text/javascript">
+var hljs=new function(){function m(p){return p.replace(/&/gm,"&").replace(/</gm,"<")}function f(r,q,p){return RegExp(q,"m"+(r.cI?"i":"")+(p?"g":""))}function b(r){for(var p=0;p<r.childNodes.length;p++){var q=r.childNodes[p];if(q.nodeName=="CODE"){return q}if(!(q.nodeType==3&&q.nodeValue.match(/\s+/))){break}}}function h(t,s){var p="";for(var r=0;r<t.childNodes.length;r++){if(t.childNodes[r].nodeType==3){var q=t.childNodes[r].nodeValue;if(s){q=q.replace(/\n/g,"")}p+=q}else{if(t.chi [...]
+hljs.initHighlightingOnLoad();
+</script>
+
+
+
+<style type="text/css">
+body, td {
+   font-family: sans-serif;
+   background-color: white;
+   font-size: 13px;
+}
+
+body {
+  max-width: 800px;
+  margin: auto;
+  padding: 1em;
+  line-height: 20px;
+}
+
+tt, code, pre {
+   font-family: 'DejaVu Sans Mono', 'Droid Sans Mono', 'Lucida Console', Consolas, Monaco, monospace;
+}
+
+h1 {
+   font-size:2.2em;
+}
+
+h2 {
+   font-size:1.8em;
+}
+
+h3 {
+   font-size:1.4em;
+}
+
+h4 {
+   font-size:1.0em;
+}
+
+h5 {
+   font-size:0.9em;
+}
+
+h6 {
+   font-size:0.8em;
+}
+
+a:visited {
+   color: rgb(50%, 0%, 50%);
+}
+
+pre, img {
+  max-width: 100%;
+}
+pre {
+  overflow-x: auto;
+}
+pre code {
+   display: block; padding: 0.5em;
+}
+
+code {
+  font-size: 92%;
+  border: 1px solid #ccc;
+}
+
+code[class] {
+  background-color: #F8F8F8;
+}
+
+table, td, th {
+  border: none;
+}
+
+blockquote {
+   color:#666666;
+   margin:0;
+   padding-left: 1em;
+   border-left: 0.5em #EEE solid;
+}
+
+hr {
+   height: 0px;
+   border-bottom: none;
+   border-top-width: thin;
+   border-top-style: dotted;
+   border-top-color: #999999;
+}
+
+ at media print {
+   * {
+      background: transparent !important;
+      color: black !important;
+      filter:none !important;
+      -ms-filter: none !important;
+   }
+
+   body {
+      font-size:12pt;
+      max-width:100%;
+   }
+
+   a, a:visited {
+      text-decoration: underline;
+   }
+
+   hr {
+      visibility: hidden;
+      page-break-before: always;
+   }
+
+   pre, blockquote {
+      padding-right: 1em;
+      page-break-inside: avoid;
+   }
+
+   tr, img {
+      page-break-inside: avoid;
+   }
+
+   img {
+      max-width: 100% !important;
+   }
+
+   @page :left {
+      margin: 15mm 20mm 15mm 10mm;
+   }
+
+   @page :right {
+      margin: 15mm 10mm 15mm 20mm;
+   }
+
+   p, h2, h3 {
+      orphans: 3; widows: 3;
+   }
+
+   h2, h3 {
+      page-break-after: avoid;
+   }
+}
+</style>
+
+<meta name="keywords" content="R, package, vignette, future, promise">
+<meta name="author" content="Henrik Bengtsson">
+
+</head>
+
+<body>
+<h1>A Future for R: Common Issues with Solutions</h1>
+
+<p>In the ideal case, all it takes to start using futures in R is to replace select standard assignments (<code><-</code>) in your R code with future assignments (<code>%<-%</code>) and make sure the right-hand side (RHS) expressions are within curly brackets (<code>{ ... }</code>).  Also, if you assign these to lists (e.g. in a for loop), you need to use a list environment (<code>listenv</code>) instead of a plain list.</p>
+
+<p>However, as show below, there are few cases where you might run into some hurdles, but, as also shown, they are often easy to overcome.  These are often related to global variables.  </p>
+
+<p><em>If you identify other cases, please consider <a href="https://github.com/HenrikBengtsson/future/issues/">reporting</a> them so they can be documented here and possibly even be fixed.</em></p>
+
+<h2>Issues with globals</h2>
+
+<h3>Missing or incorrect globals (false negatives)</h3>
+
+<h4>Global variable obscured by subassignment</h4>
+
+<p>When a global variable is a vector, a matrix, a list, a data frame, an environment, or any other type of object that can be assigned via subsetting, the global package fails to identify it as a global variable if its first occurrence in the future expression is as part of a subsetting assignment.
+For example,</p>
+
+<pre><code class="r">> library("future")
+> plan(lazy)
+> x <- matrix(1:12, nrow=3, ncol=4)
+> y %<-% {
++   x[1,1] <- 3
++   42
++ }
+> rm(x)
+> y
+Error in x[1, 1] <- 3 : object 'x' not found
+</code></pre>
+
+<p>Another example is</p>
+
+<pre><code class="r">> library("future")
+> plan(lazy)
+> x <- list(a=1, b=2)
+> y %<-% {
++   x$c <- 3
++   42
++ }
+> rm(x)
+> y
+Error in x$c <- 3 : object 'x' not found
+</code></pre>
+
+<p>A workaround is to explicitly tell the future package about the global variable by simply listing it at the beginning of the expression, e.g.</p>
+
+<pre><code class="r">> library("future")
+> plan(lazy)
+> x <- list(a=1, b=2)
+> y %<-% {
++   x  ## Force 'x' to be global
++   x$c <- 3
++   42
++ }
+> rm(x)
+> y
+[1] 42
+</code></pre>
+
+<p><em>Comment</em>: The goal is that the <a href="https://cran.r-project.org/package=globals">globals</a> package will also handle the above case in a future version.  </p>
+
+<h4>do.call() - function not found</h4>
+
+<p>When calling a function using <code>do.call()</code> make sure to specify the function as the object itself and not by name.  This will help identify the function as a global object in the future expression.  For instance, use</p>
+
+<pre><code class="r">do.call(file_ext, list("foo.txt"))
+</code></pre>
+
+<p>instead of</p>
+
+<pre><code class="r">do.call("file_ext", list("foo.txt"))
+</code></pre>
+
+<p>so that <code>file_ext()</code> is properly located and exported.  Although you may not notice a difference when evaluating futures in the same R session, it may become a problem if you use a character string instead of a function object when futures are evaluated in external R sessions, such as on a cluster.
+It may also become a problem with lazy futures if the intended function is redefined after the future is resolved.  For example,</p>
+
+<pre><code class="r">> library("future")
+> library("listenv")
+> library("tools")
+> plan(lazy)
+> pathnames <- c("foo.txt", "bar.png", "yoo.md")
+> res <- listenv()
+> for (ii in seq_along(pathnames)) {
++   res[[ii]] %<-% do.call("file_ext", list(pathnames[ii]))
++ }
+> file_ext <- function(...) "haha!"
+> unlist(res)
+[1] "haha!" "haha!" "haha!"
+</code></pre>
+
+<h2>Trying to pass an unresolved future to another future</h2>
+
+<p>It is not possible for a future to resolve another one unless it was created by the future trying to resolve it.  For instance, the following gives an error:</p>
+
+<pre><code class="r">> library("future")
+> plan(multiprocess)
+> f1 <- future({ Sys.getpid() })
+> f2 <- future({ value(f1) })
+> v1 <- value(f1)
+[1] 7464
+> v2 <- value(f2)
+Error: Invalid usage of futures: A future whose value has not yet been collected
+ can only be queried by the R process (cdd013cb-e045-f4a5-3977-9f064c31f188; pid
+ 1276 on MyMachine) that created it, not by any other R processes (5579f789-e7b6
+ -bace-c50d-6c7a23ddb5a3; pid 2352 on MyMachine): {; Sys.getpid(); }
+</code></pre>
+
+<p>This is because the main R process creates two futures, but then the second future tries to retrieve the value of the first one.  This is an invalid request because the second future has no channel to communicate with the first future; it is only the process that created a future who can communicate with it(*).</p>
+
+<p>Note that it is only <em>unresolved</em> futures that cannot be queried this way.  Thus, the solution to the above problem is to make sure all futures are resolved before they are passed to other futures, e.g.</p>
+
+<pre><code class="r">> f1 <- future({ Sys.getpid() })
+> v1 <- value(f1)
+> v1
+[1] 7464
+> f2 <- future({ value(f1) })
+> v2 <- value(f2)
+> v2
+[1] 7464
+</code></pre>
+
+<p>This works because the value has already been collected and stored inside future <code>f1</code> before future <code>f2</code> is created.  Since the value is already stored internally, <code>value(f1)</code> is readily available everywhere.  Of course, instead of using <code>value(f1)</code> for the second future, it would be more readable and cleaner to simply use <code>v1</code>.</p>
+
+<p>The above is typically not a problem when future assignments are used.  For example:</p>
+
+<pre><code class="r">> v1 %<-% { Sys.getpid() })
+> v2 %<-% { v1 }
+> v1
+[1] 2352
+> v2
+[1] 2352
+</code></pre>
+
+<p>The reason that this approach works out of the box is because in the second future assignment <code>v1</code> is identified as a global variable, which is retrieved.  Up to this point, <code>v1</code> is a promise (“delayed assignment” in R), but when it is retrieved as a global variable its value is resolved and <code>v1</code> becomes a regular variable.</p>
+
+<p>However, there are cases where future assignments can be passed via global variables without being resolved.  This can happen if the future assignment is done to an element of an environment (including list environments).  For instance,</p>
+
+<pre><code class="r">> library("listenv")
+> x <- listenv()
+> x$a %<-% { Sys.getpid() }
+> x$b %<-% { x$a }
+> x$a
+[1] 2352
+> x$b
+Error: Invalid usage of futures: A future whose value has not yet been collected
+ can only be queried by the R process (cdd013cb-e045-f4a5-3977-9f064c31f188; pid
+ 1276 on localhost) that created it, not by any other R processes (2ce86ccd-5854
+ -7a05-1373-e1b20022e4d8; pid 7464 on localhost): {; Sys.getpid(); }
+</code></pre>
+
+<p>As previously, this can be avoided by making sure <code>x$a</code> is resolved first, which can be one in various ways, e.g. <code>dummy <- x$a</code>, <code>resolve(x$a)</code> and <code>force(x$a)</code>.</p>
+
+<p><em>Footnote</em>: (*) Although certain types of futures, such as eager and lazy ones, could be passed on to other futures and be resolved there because they share the same evaluation process, by definition of the Future API it is invalid to do so regardless of future type.  This conservative approach is taken in order to make future expressions behave consistently regardless of the type of future used.</p>
+
+<h2>Miscellaneous</h2>
+
+<h3>Clashes with other packages</h3>
+
+<p>Sometimes other packages have functions or operators with the same name as the future package, and if those packages are attached <em>after</em> the future package, their objects will mask the ones of the future package.  For instance, the igraph package also defines a <code>%<-%</code> operator which clashes with the one in future <em>if used at the prompt or in a script</em> (it is not a problem inside package because there we explicitly import objects in a known order).  Here is [...]
+
+<pre><code class="r">> library("future")
+> library("igraph")
+
+Attaching package: 'igraph'
+
+The following objects are masked from 'package:future':
+
+    %<-%, %->%
+
+The following objects are masked from 'package:stats':
+
+    decompose, spectrum
+
+The following object is masked from 'package:base':
+
+    union
+
+> y %<-% { 42 }
+Error in get(".igraph.from", parent.frame()) : 
+  object '.igraph.from' not found
+</code></pre>
+
+<p>Here we get an error because <code>%<-%</code> is from igraph and not the future assignment operator as we wanted.  This can be confirmed as:</p>
+
+<pre><code class="r">> environment(`%<-%`)
+<environment: namespace:igraph>
+</code></pre>
+
+<p>To avoid this problem, attach the two packages in opposite order such that future comes last and thereby overrides igraph, i.e.</p>
+
+<pre><code class="r">> library("igraph")
+> library("future")
+
+Attaching package: 'future'
+
+The following objects are masked from 'package:igraph':
+
+%<-%, %->%
+
+> y %<-% { 42 }
+> y
+[1] 42
+</code></pre>
+
+<p>An alternative is to detach the future package and re-attach it, which will achieve the same thing:</p>
+
+<pre><code class="r">> detach("package:future")
+> library("future")
+</code></pre>
+
+<p>Yet another alternative is to explicitly override the object by importing it to the global environment, e.g.</p>
+
+<pre><code class="r">> `%<-%` <- future::`%<-%`
+> y %<-% { 42 }
+> y
+[1] 42
+</code></pre>
+
+<p>In this case, it does not matter in what order the packages are attached because we will always use the copy of <code>future::`%<-%`</code>.</p>
+
+<h3>Syntax error: “non-numeric argument to binary operator”</h3>
+
+<p>The future assignment operator <code>%<-%</code> is a <em>binary infix operator</em>, which means it has higher precedence than most other binary operators but also higher than some of the unary operators in R.  For instance, this explains why we get the following error:</p>
+
+<pre><code class="r">> x %<-% 2 * runif(1)
+Error in x %<-% 2 * runif(1) : non-numeric argument to binary operator
+</code></pre>
+
+<p>What effectively is happening here is that because of the higher priority of <code>%<-%</code>, we first create a future <code>x %<-% 2</code> and then we try to multiply the future (not its value) with the value of <code>runif(1)</code> - which makes no sense.  In order to properly assign the future variable, we need to put the future expression within curly brackets;</p>
+
+<pre><code class="r">> x %<-% { 2 * runif(1) }
+> x
+[1] 1.030209
+</code></pre>
+
+<p>Parentheses will also do.  For details on precedence on operators in R, see Section 'Infix and prefix operators' in the 'R Language Definition' document.</p>
+
+<hr/>
+
+<p>Copyright Henrik Bengtsson, 2015-2016</p>
+
+</body>
+
+</html>
diff --git a/inst/doc/future-2-issues.md.rsp b/inst/doc/future-2-issues.md.rsp
new file mode 100644
index 0000000..bd916df
--- /dev/null
+++ b/inst/doc/future-2-issues.md.rsp
@@ -0,0 +1,322 @@
+<%@meta language="R-vignette" content="--------------------------------
+%\VignetteIndexEntry{A Future for R: Common Issues with Solutions}
+%\VignetteAuthor{Henrik Bengtsson}
+%\VignetteKeyword{R}
+%\VignetteKeyword{package}
+%\VignetteKeyword{vignette}
+%\VignetteKeyword{future}
+%\VignetteKeyword{promise}
+%\VignetteEngine{R.rsp::rsp}
+%\VignetteTangle{FALSE}
+--------------------------------------------------------------------"%>
+# <%@meta name="title"%>
+
+In the ideal case, all it takes to start using futures in R is to replace select standard assignments (`<-`) in your R code with future assignments (`%<-%`) and make sure the right-hand side (RHS) expressions are within curly brackets (`{ ... }`).  Also, if you assign these to lists (e.g. in a for loop), you need to use a list environment (`listenv`) instead of a plain list.
+
+However, as show below, there are few cases where you might run into some hurdles, but, as also shown, they are often easy to overcome.  These are often related to global variables.  
+
+_If you identify other cases, please consider [reporting](https://github.com/HenrikBengtsson/future/issues/) them so they can be documented here and possibly even be fixed._
+
+
+## Issues with globals
+
+
+### Missing or incorrect globals (false negatives)
+
+#### Global variable obscured by subassignment
+When a global variable is a vector, a matrix, a list, a data frame, an environment, or any other type of object that can be assigned via subsetting, the global package fails to identify it as a global variable if its first occurrence in the future expression is as part of a subsetting assignment.
+For example,
+```r
+> library("future")
+> plan(lazy)
+> x <- matrix(1:12, nrow=3, ncol=4)
+> y %<-% {
++   x[1,1] <- 3
++   42
++ }
+> rm(x)
+> y
+Error in x[1, 1] <- 3 : object 'x' not found
+```
+Another example is
+```r
+> library("future")
+> plan(lazy)
+> x <- list(a=1, b=2)
+> y %<-% {
++   x$c <- 3
++   42
++ }
+> rm(x)
+> y
+Error in x$c <- 3 : object 'x' not found
+```
+A workaround is to explicitly tell the future package about the global variable by simply listing it at the beginning of the expression, e.g.
+```r
+> library("future")
+> plan(lazy)
+> x <- list(a=1, b=2)
+> y %<-% {
++   x  ## Force 'x' to be global
++   x$c <- 3
++   42
++ }
+> rm(x)
+> y
+[1] 42
+```
+
+_Comment_: The goal is that the [globals] package will also handle the above case in a future version.  
+
+
+
+#### do.call() - function not found
+When calling a function using `do.call()` make sure to specify the function as the object itself and not by name.  This will help identify the function as a global object in the future expression.  For instance, use
+```r
+do.call(file_ext, list("foo.txt"))
+```
+instead of
+```r
+do.call("file_ext", list("foo.txt"))
+```
+so that `file_ext()` is properly located and exported.  Although you may not notice a difference when evaluating futures in the same R session, it may become a problem if you use a character string instead of a function object when futures are evaluated in external R sessions, such as on a cluster.
+It may also become a problem with lazy futures if the intended function is redefined after the future is resolved.  For example,
+```r
+> library("future")
+> library("listenv")
+> library("tools")
+> plan(lazy)
+> pathnames <- c("foo.txt", "bar.png", "yoo.md")
+> res <- listenv()
+> for (ii in seq_along(pathnames)) {
++   res[[ii]] %<-% do.call("file_ext", list(pathnames[ii]))
++ }
+> file_ext <- function(...) "haha!"
+> unlist(res)
+[1] "haha!" "haha!" "haha!"
+```
+
+<%---
+### False globals due to non-standard evaluation (false positives)
+
+#### subset(data, x < 3)
+
+Consider the following use of `subset()`:
+```r
+> data <- data.frame(x=1:5, y=1:5)
+> v <- subset(data, x < 3)$y
+> v
+[1] 1 2
+```
+From a static code inspection point of view, the expression `x < 3` asks for variable `x` to be compared to 3, and there is nothing specifying that `x` is part of `data` and not the global environment.  That `x` is indeed part of the `data` object can only safely be inferred at runtime when `subset()` is called.  This is not a problem in the above snippet, but when using futures all global/unknown variables need to be captured when the future is created (it is too late to do it when the  [...]
+```r
+> library("future")
+> data <- data.frame(x=1:5, y=1:5)
+> v %<-% subset(data, x < 3)$y
+Error in globalsOf(expr, envir = envir, tweak = tweakExpression, dotdotdot = "return",  :
+  Identified a global by static code inspection, but failed to locate the corresponding
+  object in the relevant environments: 'x'
+```
+Above, code inspection of the future expression `subset(data, x < 3)$y` incorrectly identifies `x` as a global variables that needs to be captured ("frozen") for the (lazy) future.  Since no such variable `x` exists, we get an error.
+
+A clearer and backward-compatible solution to this problem is to explicitly specify the context of `x`, i.e.
+```r
+> data <- data.frame(x=1:5, y=1:5)
+> v %<-% subset(data, data$x < 3)$y
+> v
+[1] 1 2
+```
+
+An alternative is to use a dummy variable.  In contrast to the code-inspection algorithm used to identify globals, _we know from reading the documentation_ that `subset()` will look for `x` in the `data` object, not in the parent environments.  Armed with this knowledge, we can trick the [future] package (more precisely the [globals] package) to pick up a dummy variable `x` instead, e.g.
+```r
+> data <- data.frame(x=1:5, y=1:5)
+> x <- NULL ## To please future et al.
+> v %<-% subset(data, x < 3)$y
+> v
+[1] 1 2
+```
+
+#### ggplot2
+Another common use case for non-standard evaluation is when creating ggplot2 figures.  For instance, in
+```r
+> library("ggplot2")
+> p <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
+> p
+```
+fields `mpg` and `wt` of the `mtcars` data object are plotted against each other.  That `mpg` and `wt` are fields of `mtcars` cannot be inferred from code inspection alone, but you need to know that that is how ggplot2 works.  Analogously to the above `subset()` example, this explains why we get the following error:
+```r
+> library("future")
+> library("ggplot2")
+> p %<-% { ggplot(mtcars, aes(wt, mpg)) + geom_point() }
+Error in globalsOf(expr, envir = envir, tweak = tweakExpression, dotdotdot = "return",  :
+  Identified a global by static code inspection, but failed to locate the corresponding
+  object in the relevant environments: 'wt'
+```
+A few comments are needed here.  First of all, because `%<-%` has higher precedence than `+`, we need to place all of the ggplot2 expression within curly brackets, otherwise, we get an error.  Second, the reason for only `wt` being listed as a missing global variable and not `mpg` is because the latter is (incorrectly) located to be `ggplot2::mpg`.
+
+One workaround is to make use of the `*_string()` functions of ggplot2, e.g.
+```r
+> p %<-% { ggplot(mtcars, aes_string('wt', 'mpg')) + geom_point() }
+> p
+```
+Another one, is to explicitly specify `mtcars$wt` and `mtcars$mpg`, which may become a bit tedious.
+A third alternative is to make use of dummy variables `wt` and `mpg`, i.e.
+```r
+> p %<-% {
++   wt <- mpg <- NULL
++   ggplot(mtcars, aes(wt, mpg)) + geom_point()
++ }
+> p
+```
+By the way, since all futures are evaluated in a local environment, the dummy variables are _not_ assigned to the calling environment.
+---%>
+
+
+## Trying to pass an unresolved future to another future
+It is not possible for a future to resolve another one unless it was created by the future trying to resolve it.  For instance, the following gives an error:
+```r
+> library("future")
+> plan(multiprocess)
+> f1 <- future({ Sys.getpid() })
+> f2 <- future({ value(f1) })
+> v1 <- value(f1)
+[1] 7464
+> v2 <- value(f2)
+Error: Invalid usage of futures: A future whose value has not yet been collected
+ can only be queried by the R process (cdd013cb-e045-f4a5-3977-9f064c31f188; pid
+ 1276 on MyMachine) that created it, not by any other R processes (5579f789-e7b6
+ -bace-c50d-6c7a23ddb5a3; pid 2352 on MyMachine): {; Sys.getpid(); }
+```
+This is because the main R process creates two futures, but then the second future tries to retrieve the value of the first one.  This is an invalid request because the second future has no channel to communicate with the first future; it is only the process that created a future who can communicate with it(*).
+
+Note that it is only _unresolved_ futures that cannot be queried this way.  Thus, the solution to the above problem is to make sure all futures are resolved before they are passed to other futures, e.g.
+```r
+> f1 <- future({ Sys.getpid() })
+> v1 <- value(f1)
+> v1
+[1] 7464
+> f2 <- future({ value(f1) })
+> v2 <- value(f2)
+> v2
+[1] 7464
+```
+This works because the value has already been collected and stored inside future `f1` before future `f2` is created.  Since the value is already stored internally, `value(f1)` is readily available everywhere.  Of course, instead of using `value(f1)` for the second future, it would be more readable and cleaner to simply use `v1`.
+
+The above is typically not a problem when future assignments are used.  For example:
+```r
+> v1 %<-% { Sys.getpid() })
+> v2 %<-% { v1 }
+> v1
+[1] 2352
+> v2
+[1] 2352
+```
+The reason that this approach works out of the box is because in the second future assignment `v1` is identified as a global variable, which is retrieved.  Up to this point, `v1` is a promise ("delayed assignment" in R), but when it is retrieved as a global variable its value is resolved and `v1` becomes a regular variable.
+
+However, there are cases where future assignments can be passed via global variables without being resolved.  This can happen if the future assignment is done to an element of an environment (including list environments).  For instance,
+```r
+> library("listenv")
+> x <- listenv()
+> x$a %<-% { Sys.getpid() }
+> x$b %<-% { x$a }
+> x$a
+[1] 2352
+> x$b
+Error: Invalid usage of futures: A future whose value has not yet been collected
+ can only be queried by the R process (cdd013cb-e045-f4a5-3977-9f064c31f188; pid
+ 1276 on localhost) that created it, not by any other R processes (2ce86ccd-5854
+ -7a05-1373-e1b20022e4d8; pid 7464 on localhost): {; Sys.getpid(); }
+```
+As previously, this can be avoided by making sure `x$a` is resolved first, which can be one in various ways, e.g. `dummy <- x$a`, `resolve(x$a)` and `force(x$a)`.
+
+_Footnote_: (*) Although certain types of futures, such as eager and lazy ones, could be passed on to other futures and be resolved there because they share the same evaluation process, by definition of the Future API it is invalid to do so regardless of future type.  This conservative approach is taken in order to make future expressions behave consistently regardless of the type of future used.
+
+
+## Miscellaneous
+
+### Clashes with other packages
+
+Sometimes other packages have functions or operators with the same name as the future package, and if those packages are attached _after_ the future package, their objects will mask the ones of the future package.  For instance, the igraph package also defines a `%<-%` operator which clashes with the one in future _if used at the prompt or in a script_ (it is not a problem inside package because there we explicitly import objects in a known order).  Here is what we might get:
+```r
+> library("future")
+> library("igraph")
+
+Attaching package: 'igraph'
+
+The following objects are masked from 'package:future':
+
+    %<-%, %->%
+
+The following objects are masked from 'package:stats':
+
+    decompose, spectrum
+
+The following object is masked from 'package:base':
+
+    union
+
+> y %<-% { 42 }
+Error in get(".igraph.from", parent.frame()) : 
+  object '.igraph.from' not found
+```
+Here we get an error because `%<-%` is from igraph and not the future assignment operator as we wanted.  This can be confirmed as:
+```r
+> environment(`%<-%`)
+<environment: namespace:igraph>
+```
+
+To avoid this problem, attach the two packages in opposite order such that future comes last and thereby overrides igraph, i.e.
+```r
+> library("igraph")
+> library("future")
+
+Attaching package: 'future'
+
+The following objects are masked from 'package:igraph':
+
+%<-%, %->%
+
+> y %<-% { 42 }
+> y
+[1] 42
+```
+
+An alternative is to detach the future package and re-attach it, which will achieve the same thing:
+```r
+> detach("package:future")
+> library("future")
+```
+
+Yet another alternative is to explicitly override the object by importing it to the global environment, e.g.
+```r
+> `%<-%` <- future::`%<-%`
+> y %<-% { 42 }
+> y
+[1] 42
+```
+In this case, it does not matter in what order the packages are attached because we will always use the copy of `` future::`%<-%` ``.
+
+
+
+### Syntax error: "non-numeric argument to binary operator"
+The future assignment operator `%<-%` is a _binary infix operator_, which means it has higher precedence than most other binary operators but also higher than some of the unary operators in R.  For instance, this explains why we get the following error:
+```r
+> x %<-% 2 * runif(1)
+Error in x %<-% 2 * runif(1) : non-numeric argument to binary operator
+```
+What effectively is happening here is that because of the higher priority of `%<-%`, we first create a future `x %<-% 2` and then we try to multiply the future (not its value) with the value of `runif(1)` - which makes no sense.  In order to properly assign the future variable, we need to put the future expression within curly brackets;
+```r
+> x %<-% { 2 * runif(1) }
+> x
+[1] 1.030209
+```
+Parentheses will also do.  For details on precedence on operators in R, see Section 'Infix and prefix operators' in the 'R Language Definition' document.
+
+
+
+[future]: https://cran.r-project.org/package=future
+[globals]: https://cran.r-project.org/package=globals
+[listenv]: https://cran.r-project.org/package=listenv
+
+---
+Copyright Henrik Bengtsson, 2015-2016
diff --git a/inst/doc/future-3-topologies.html b/inst/doc/future-3-topologies.html
new file mode 100644
index 0000000..bca3084
--- /dev/null
+++ b/inst/doc/future-3-topologies.html
@@ -0,0 +1,367 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+
+<title>A Future for R: Future Topologies</title>
+
+<script type="text/javascript">
+window.onload = function() {
+  var imgs = document.getElementsByTagName('img'), i, img;
+  for (i = 0; i < imgs.length; i++) {
+    img = imgs[i];
+    // center an image if it is the only element of its parent
+    if (img.parentElement.childElementCount === 1)
+      img.parentElement.style.textAlign = 'center';
+  }
+};
+</script>
+
+<!-- Styles for R syntax highlighter -->
+<style type="text/css">
+   pre .operator,
+   pre .paren {
+     color: rgb(104, 118, 135)
+   }
+
+   pre .literal {
+     color: #990073
+   }
+
+   pre .number {
+     color: #099;
+   }
+
+   pre .comment {
+     color: #998;
+     font-style: italic
+   }
+
+   pre .keyword {
+     color: #900;
+     font-weight: bold
+   }
+
+   pre .identifier {
+     color: rgb(0, 0, 0);
+   }
+
+   pre .string {
+     color: #d14;
+   }
+</style>
+
+<!-- R syntax highlighter -->
+<script type="text/javascript">
+var hljs=new function(){function m(p){return p.replace(/&/gm,"&").replace(/</gm,"<")}function f(r,q,p){return RegExp(q,"m"+(r.cI?"i":"")+(p?"g":""))}function b(r){for(var p=0;p<r.childNodes.length;p++){var q=r.childNodes[p];if(q.nodeName=="CODE"){return q}if(!(q.nodeType==3&&q.nodeValue.match(/\s+/))){break}}}function h(t,s){var p="";for(var r=0;r<t.childNodes.length;r++){if(t.childNodes[r].nodeType==3){var q=t.childNodes[r].nodeValue;if(s){q=q.replace(/\n/g,"")}p+=q}else{if(t.chi [...]
+hljs.initHighlightingOnLoad();
+</script>
+
+
+
+<style type="text/css">
+body, td {
+   font-family: sans-serif;
+   background-color: white;
+   font-size: 13px;
+}
+
+body {
+  max-width: 800px;
+  margin: auto;
+  padding: 1em;
+  line-height: 20px;
+}
+
+tt, code, pre {
+   font-family: 'DejaVu Sans Mono', 'Droid Sans Mono', 'Lucida Console', Consolas, Monaco, monospace;
+}
+
+h1 {
+   font-size:2.2em;
+}
+
+h2 {
+   font-size:1.8em;
+}
+
+h3 {
+   font-size:1.4em;
+}
+
+h4 {
+   font-size:1.0em;
+}
+
+h5 {
+   font-size:0.9em;
+}
+
+h6 {
+   font-size:0.8em;
+}
+
+a:visited {
+   color: rgb(50%, 0%, 50%);
+}
+
+pre, img {
+  max-width: 100%;
+}
+pre {
+  overflow-x: auto;
+}
+pre code {
+   display: block; padding: 0.5em;
+}
+
+code {
+  font-size: 92%;
+  border: 1px solid #ccc;
+}
+
+code[class] {
+  background-color: #F8F8F8;
+}
+
+table, td, th {
+  border: none;
+}
+
+blockquote {
+   color:#666666;
+   margin:0;
+   padding-left: 1em;
+   border-left: 0.5em #EEE solid;
+}
+
+hr {
+   height: 0px;
+   border-bottom: none;
+   border-top-width: thin;
+   border-top-style: dotted;
+   border-top-color: #999999;
+}
+
+ at media print {
+   * {
+      background: transparent !important;
+      color: black !important;
+      filter:none !important;
+      -ms-filter: none !important;
+   }
+
+   body {
+      font-size:12pt;
+      max-width:100%;
+   }
+
+   a, a:visited {
+      text-decoration: underline;
+   }
+
+   hr {
+      visibility: hidden;
+      page-break-before: always;
+   }
+
+   pre, blockquote {
+      padding-right: 1em;
+      page-break-inside: avoid;
+   }
+
+   tr, img {
+      page-break-inside: avoid;
+   }
+
+   img {
+      max-width: 100% !important;
+   }
+
+   @page :left {
+      margin: 15mm 20mm 15mm 10mm;
+   }
+
+   @page :right {
+      margin: 15mm 10mm 15mm 20mm;
+   }
+
+   p, h2, h3 {
+      orphans: 3; widows: 3;
+   }
+
+   h2, h3 {
+      page-break-after: avoid;
+   }
+}
+</style>
+
+<meta name="keywords" content="R, package, vignette, future, promise">
+<meta name="author" content="Henrik Bengtsson">
+
+</head>
+
+<body>
+<h1>A Future for R: Future Topologies</h1>
+
+<p>Futures can be nested in R such that one future creates another set of futures and so on.  This may, for instance, occur within nested for loops, e.g.</p>
+
+<pre><code class="r">library("future")
+library("listenv")
+x <- listenv()
+for (ii in 1:3) {
+  x[[ii]] %<-% {
+    y <- listenv()
+    for (jj in 1:3) {
+      y[[jj]] %<-% { ii + jj/10 }
+    }
+    y
+  }
+}
+unlist(x)
+## [1] 1.1 1.2 1.3 2.1 2.2 2.3 3.1 3.2 3.3
+</code></pre>
+
+<p>The default is to use eager futures unless otherwise specified, which is also true for nested futures.  If we for instance specify, <code>plan(multiprocess)</code>, the first layer of futures (<code>x[[ii]] %<-% { expr }</code>) will be processed asynchronously in background R processes, and the futures in the second layer of futures (<code>y[[jj]] %<-% { expr }</code>) will be processed synchronously in the current R processes (one of the background processes).  If we wish to u [...]
+
+<h2>Example: High-Throughput Sequencing</h2>
+
+<p>Consider a high-throughput sequencing (HT-Seq) project with 50 human DNA samples where we have one FASTQ file per sample containing the raw sequence reads as they come out of the sequencing machine.  With this data, we wish to align each FASTQ to a reference genome such that we generate 24 individual BAM files per sample - one per chromosome.</p>
+
+<p>Here is the layout of what such an analysis could look like in R using futures.</p>
+
+<pre><code class="r">library("future")
+library("listenv")
+htseq_align <- function(fq, chr) { chr }
+
+fqs <- dir(pattern="[.]fastq$")
+
+bams <- listenv()
+for (ss in seq_along(fqs)) {
+  fq <- fqs[ss]
+  bams[[ss]] %<-% {
+    bams_ss <- listenv()
+    for (cc in 1:24) {
+      bams_ss[[cc]] %<-% htseq_align(fq, chr=cc)
+    }
+    as.list(bams_ss)
+  }
+}
+bams <- as.list(bams)
+</code></pre>
+
+<p>The default is to use eager futures, so without further specifications, the above will process each sample and each chromosome sequentially.  Next, we will consider what can be done with the following two computer setups:</p>
+
+<ul>
+<li>A single machine with 8 cores</li>
+<li>A compute cluster with 3 machines each with 16 cores</li>
+</ul>
+
+<h3>One multi-core machine</h3>
+
+<p>With a single machine of 8 cores, we could choose to process multiple samples at the same while processing chromosomes sequentially.  In other words, we would like to evaluate the outer layer of futures using multiprocess futures and the inner ones as regular (uniprocess) eager futures.  This can be specified as:</p>
+
+<pre><code class="r">plan(list(multiprocess, eager))
+</code></pre>
+
+<p>The internals for processing multiprocess future queries <code>availableCores()</code> to infer how many cores can be used simultaneously, so there is no need to explicitly specify that there are 8 cores available.</p>
+
+<p><em>Comment</em>: Since eager is the default future, we could skip trailing eager futures in the setup, e.g. <code>plan(list(multiprocess))</code> or just <code>plan(multiprocess)</code>.  However, it does hurt to be explicit.</p>
+
+<p>If we instead would like to process the sample sequentially and the chromosomes in parallel, we can use:</p>
+
+<pre><code class="r">plan(list(eager, multiprocess))
+</code></pre>
+
+<p>We could also process the data such that we allocate two cores for processing two samples in parallel each using four cores for processing four chromosomes in parallel:</p>
+
+<pre><code class="r">plan(list(tweak(multiprocess, workers=2), tweak(multiprocess, workers=4)))
+</code></pre>
+
+<h3>An ad-hoc compute cluster</h3>
+
+<p>With a compute cluster of 3 machines each with 16 cores, we can run up to 48 alignment processes in parallel.  A natural setup is to have one machine process one sample in parallel.  We could specify this as:</p>
+
+<pre><code class="r">nodes <- c("n1", "n2", "n3")
+plan(list(tweak(cluster, workers=nodes), multiprocess))
+</code></pre>
+
+<p><em>Comment:</em> Multiprocess futures are agile to its environment, that is, they will query the machine they are running on to find out how many parallel processes it can run at the same time.</p>
+
+<p>One possible downside to the above setup is that we might not utilize all available cores all the time.  This is because the alignment of the shorter chromosomes will finish sooner than the longer ones, which means that we might at the end of each sample have only a few alignment processes running on each machine leaving the remaining cores idle/unused.  An alternative set up is then to use the following setup:</p>
+
+<pre><code class="r">nodes <- rep(c("n1", "n2", "n3"), each=8)
+plan(list(tweak(cluster, workers=nodes), multiprocess))
+</code></pre>
+
+<p>This will cause up to 24 (=3*8) samples to be processed in parallel each processing two chromosomes at the same time.</p>
+
+<h2>Example: A remote compute cluster</h2>
+
+<p>Imagine we have access to a remote compute cluster, with login node <code>remote.server.org</code>, and that the cluster has three nodes <code>n1</code>, <code>n2</code>, and <code>n3</code>.  Also, let us assume we have already set up the cluster such that we can log in via public key authentication via SSH, i.e. when we do <code>ssh remote.server.org</code> authentication is done automatically.</p>
+
+<p>With the above setup, we can use nested futures in our local R session to evaluate R expression on the remote compute cluster and its three nodes.  Here is a proof of concept illustrating how the different nested futures are evaluated on different machines.</p>
+
+<pre><code class="r">library("future")
+library("listenv")
+
+## Set up access to remote login node
+login <- tweak(remote, workers="remote.server.org")
+plan(login)
+
+## Set up cluster nodes on login node
+nodes %<-% { .keepme <- parallel::makeCluster(c("n1", "n2", "n3")) }
+
+## Specify future topology
+## login node -> { cluster nodes } -> { multiple cores }
+plan(list(
+  login,
+  tweak(cluster, workers=nodes),
+  multiprocess
+))
+
+
+## (a) This will be evaluated on the cluster login computer
+x %<-% {
+  thost <- Sys.info()[["nodename"]]
+  tpid <- Sys.getpid()
+  y <- listenv()
+  for (task in 1:4) {
+    ## (b) This will be evaluated on a compute node on the cluster
+    y[[task]] %<-% {
+      mhost <- Sys.info()[["nodename"]]
+      mpid <- Sys.getpid()
+      z <- listenv()
+      for (jj in 1:2) {
+        ## (c) These will be evaluated in separate processes on the same compute node
+        z[[jj]] %<-% data.frame(task=task, top.host=thost, top.pid=tpid,
+                                mid.host=mhost, mid.pid=mpid,
+                                host=Sys.info()[["nodename"]], pid=Sys.getpid())
+      }
+      Reduce(rbind, z)
+    }
+  }
+  Reduce(rbind, y)
+}
+
+print(x)
+##   task top.host top.pid mid.host mid.pid host    pid
+## 1    1    login  391547       n1  391878   n1 393943
+## 2    1    login  391547       n1  391878   n1 393951
+## 3    2    login  391547       n2  392204   n2 393971
+## 4    2    login  391547       n2  392204   n2 393978
+## 5    3    login  391547       n3  392527   n3 394040
+## 6    3    login  391547       n3  392527   n3 394048
+## 7    4    login  391547       n1  391878   n1 393959
+## 8    4    login  391547       n1  391878   n1 393966
+</code></pre>
+
+<p>Try the above <code>x %<-% { ... }</code> future with, say, <code>plan(list(lazy, multiprocess))</code> or <code>plan(list(eager, lazy, multiprocess))</code> and see what the output will be.</p>
+
+<hr/>
+
+<p>Copyright Henrik Bengtsson, 2015-2016</p>
+
+</body>
+
+</html>
diff --git a/inst/doc/future-3-topologies.md.rsp b/inst/doc/future-3-topologies.md.rsp
new file mode 100644
index 0000000..7b1ba5c
--- /dev/null
+++ b/inst/doc/future-3-topologies.md.rsp
@@ -0,0 +1,174 @@
+<%@meta language="R-vignette" content="--------------------------------
+%\VignetteIndexEntry{A Future for R: Future Topologies}
+%\VignetteAuthor{Henrik Bengtsson}
+%\VignetteKeyword{R}
+%\VignetteKeyword{package}
+%\VignetteKeyword{vignette}
+%\VignetteKeyword{future}
+%\VignetteKeyword{promise}
+%\VignetteEngine{R.rsp::rsp}
+%\VignetteTangle{FALSE}
+--------------------------------------------------------------------"%>
+<%
+library("R.utils")
+`%<-%` <- future::`%<-%`
+options("withCapture/newline"=FALSE)
+%>
+
+# <%@meta name="title"%>
+
+Futures can be nested in R such that one future creates another set of futures and so on.  This may, for instance, occur within nested for loops, e.g.
+```r
+library("future")
+library("listenv")
+x <- listenv()
+for (ii in 1:3) {
+  x[[ii]] %<-% {
+    y <- listenv()
+    for (jj in 1:3) {
+      y[[jj]] %<-% { ii + jj/10 }
+    }
+	y
+  }
+}
+unlist(x)
+## [1] 1.1 1.2 1.3 2.1 2.2 2.3 3.1 3.2 3.3
+```
+The default is to use eager futures unless otherwise specified, which is also true for nested futures.  If we for instance specify, `plan(multiprocess)`, the first layer of futures (`x[[ii]] %<-% { expr }`) will be processed asynchronously in background R processes, and the futures in the second layer of futures (`y[[jj]] %<-% { expr }`) will be processed synchronously in the current R processes (one of the background processes).  If we wish to use a different strategy for the second lay [...]
+
+
+## Example: High-Throughput Sequencing
+Consider a high-throughput sequencing (HT-Seq) project with 50 human DNA samples where we have one FASTQ file per sample containing the raw sequence reads as they come out of the sequencing machine.  With this data, we wish to align each FASTQ to a reference genome such that we generate 24 individual BAM files per sample - one per chromosome.
+
+Here is the layout of what such an analysis could look like in R using futures.
+```r
+library("future")
+library("listenv")
+htseq_align <- function(fq, chr) { chr }
+
+fqs <- dir(pattern="[.]fastq$")
+
+bams <- listenv()
+for (ss in seq_along(fqs)) {
+  fq <- fqs[ss]
+  bams[[ss]] %<-% {
+    bams_ss <- listenv()
+    for (cc in 1:24) {
+      bams_ss[[cc]] %<-% htseq_align(fq, chr=cc)
+    }
+    as.list(bams_ss)
+  }
+}
+bams <- as.list(bams)
+```
+
+The default is to use eager futures, so without further specifications, the above will process each sample and each chromosome sequentially.  Next, we will consider what can be done with the following two computer setups:
+
+* A single machine with 8 cores
+* A compute cluster with 3 machines each with 16 cores
+
+### One multi-core machine
+With a single machine of 8 cores, we could choose to process multiple samples at the same while processing chromosomes sequentially.  In other words, we would like to evaluate the outer layer of futures using multiprocess futures and the inner ones as regular (uniprocess) eager futures.  This can be specified as:
+```r
+plan(list(multiprocess, eager))
+```
+The internals for processing multiprocess future queries `availableCores()` to infer how many cores can be used simultaneously, so there is no need to explicitly specify that there are 8 cores available.
+
+_Comment_: Since eager is the default future, we could skip trailing eager futures in the setup, e.g. `plan(list(multiprocess))` or just `plan(multiprocess)`.  However, it does hurt to be explicit.
+
+If we instead would like to process the sample sequentially and the chromosomes in parallel, we can use:
+```r
+plan(list(eager, multiprocess))
+```
+
+We could also process the data such that we allocate two cores for processing two samples in parallel each using four cores for processing four chromosomes in parallel:
+```r
+plan(list(tweak(multiprocess, workers=2), tweak(multiprocess, workers=4)))
+```
+
+
+### An ad-hoc compute cluster
+With a compute cluster of 3 machines each with 16 cores, we can run up to 48 alignment processes in parallel.  A natural setup is to have one machine process one sample in parallel.  We could specify this as:
+```r
+nodes <- c("n1", "n2", "n3")
+plan(list(tweak(cluster, workers=nodes), multiprocess))
+```
+_Comment:_ Multiprocess futures are agile to its environment, that is, they will query the machine they are running on to find out how many parallel processes it can run at the same time.
+
+One possible downside to the above setup is that we might not utilize all available cores all the time.  This is because the alignment of the shorter chromosomes will finish sooner than the longer ones, which means that we might at the end of each sample have only a few alignment processes running on each machine leaving the remaining cores idle/unused.  An alternative set up is then to use the following setup:
+```r
+nodes <- rep(c("n1", "n2", "n3"), each=8)
+plan(list(tweak(cluster, workers=nodes), multiprocess))
+```
+This will cause up to 24 (=3*8) samples to be processed in parallel each processing two chromosomes at the same time.
+
+
+## Example: A remote compute cluster
+Imagine we have access to a remote compute cluster, with login node `remote.server.org`, and that the cluster has three nodes `n1`, `n2`, and `n3`.  Also, let us assume we have already set up the cluster such that we can log in via public key authentication via SSH, i.e. when we do `ssh remote.server.org` authentication is done automatically.
+
+With the above setup, we can use nested futures in our local R session to evaluate R expression on the remote compute cluster and its three nodes.  Here is a proof of concept illustrating how the different nested futures are evaluated on different machines.
+
+```r
+library("future")
+library("listenv")
+
+## Set up access to remote login node
+login <- tweak(remote, workers="remote.server.org")
+plan(login)
+
+## Set up cluster nodes on login node
+nodes %<-% { .keepme <- parallel::makeCluster(c("n1", "n2", "n3")) }
+
+## Specify future topology
+## login node -> { cluster nodes } -> { multiple cores }
+plan(list(
+  login,
+  tweak(cluster, workers=nodes),
+  multiprocess
+))
+
+
+## (a) This will be evaluated on the cluster login computer
+x %<-% {
+  thost <- Sys.info()[["nodename"]]
+  tpid <- Sys.getpid()
+  y <- listenv()
+  for (task in 1:4) {
+    ## (b) This will be evaluated on a compute node on the cluster
+    y[[task]] %<-% {
+      mhost <- Sys.info()[["nodename"]]
+      mpid <- Sys.getpid()
+      z <- listenv()
+      for (jj in 1:2) {
+        ## (c) These will be evaluated in separate processes on the same compute node
+        z[[jj]] %<-% data.frame(task=task, top.host=thost, top.pid=tpid,
+                                mid.host=mhost, mid.pid=mpid,
+                                host=Sys.info()[["nodename"]], pid=Sys.getpid())
+      }
+      Reduce(rbind, z)
+    }
+  }
+  Reduce(rbind, y)
+}
+
+print(x)
+##   task top.host top.pid mid.host mid.pid host    pid
+## 1    1    login  391547       n1  391878   n1 393943
+## 2    1    login  391547       n1  391878   n1 393951
+## 3    2    login  391547       n2  392204   n2 393971
+## 4    2    login  391547       n2  392204   n2 393978
+## 5    3    login  391547       n3  392527   n3 394040
+## 6    3    login  391547       n3  392527   n3 394048
+## 7    4    login  391547       n1  391878   n1 393959
+## 8    4    login  391547       n1  391878   n1 393966
+```
+
+Try the above `x %<-% { ... }` future with, say, `plan(list(lazy, multiprocess))` or `plan(list(eager, lazy, multiprocess))` and see what the output will be.
+
+
+[listenv]: http://cran.r-project.org/package=listenv
+[globals]: http://cran.r-project.org/package=globals
+[Futures in R: Common issues with solutions]: future-issues.html
+
+---
+Copyright Henrik Bengtsson, 2015-2016
diff --git a/inst/vignettes-static/incl/future-1-overview-example2.R b/inst/vignettes-static/incl/future-1-overview-example2.R
new file mode 100644
index 0000000..be2885a
--- /dev/null
+++ b/inst/vignettes-static/incl/future-1-overview-example2.R
@@ -0,0 +1,20 @@
+pid <- Sys.getpid()
+pid
+a %<-% {
+  pid <- Sys.getpid()
+  cat("Resolving 'a' ...\n")
+  3.14
+}
+b %<-% {
+  rm(pid)
+  cat("Resolving 'b' ...\n")
+  Sys.getpid()
+}
+c %<-% {
+  cat("Resolving 'c' ...\n")
+  2 * a
+}
+b
+c
+a
+pid
diff --git a/inst/vignettes-static/incl/future-1-overview-example3.R b/inst/vignettes-static/incl/future-1-overview-example3.R
new file mode 100644
index 0000000..54527a9
--- /dev/null
+++ b/inst/vignettes-static/incl/future-1-overview-example3.R
@@ -0,0 +1,19 @@
+pid <- Sys.getpid()
+
+a %<-% {
+  cat("Resolving 'a' ...\n")
+  Sys.getpid()
+}
+
+b %<-% {
+  cat("Resolving 'b' ...\n")
+  b1 %<-% {
+    cat("Resolving 'b1' ...\n")
+    Sys.getpid()
+  }
+  b2 %<-% {
+    cat("Resolving 'b2' ...\n")
+    Sys.getpid()
+  }
+  c(b.pid=Sys.getpid(), b1.pid=b1, b2.pid=b2)
+}
diff --git a/man/ClusterFuture-class.Rd b/man/ClusterFuture-class.Rd
new file mode 100644
index 0000000..ad469af
--- /dev/null
+++ b/man/ClusterFuture-class.Rd
@@ -0,0 +1,50 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ClusterFuture-class.R
+\name{ClusterFuture-class}
+\alias{ClusterFuture}
+\alias{ClusterFuture-class}
+\alias{MultisessionFuture}
+\alias{MultisessionFuture-class}
+\title{A cluster future is a future whose value will be resolved asynchroneously in a parallel process}
+\usage{
+ClusterFuture(expr = NULL, envir = parent.frame(), substitute = FALSE,
+  local = !persistent, gc = !persistent, persistent = FALSE,
+  workers = NULL, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE).}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{local}{If TRUE, the expression is evaluated such that
+all assignments are done to local temporary environment, otherwise
+the assignments are done in the global environment of the cluster node.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{persistent}{If FALSE, the evaluation environment is cleared
+from objects prior to the evaluation of the future.}
+
+\item{workers}{A \code{\link[parallel:makeCluster]{cluster}}.
+Alternatively, a character vector of host names or a numeric scalar,
+for creating a cluster via \code{\link[parallel]{makeCluster}(workers)}.}
+
+\item{\dots}{Additional named elements of the future.}
+}
+\value{
+An object of class \code{ClusterFuture}.
+}
+\description{
+A cluster future is a future whose value will be resolved asynchroneously in a parallel process
+}
+\seealso{
+To evaluate an expression using "cluster future", see function
+\code{\link{cluster}()}.
+}
+\keyword{internal}
+
diff --git a/man/ConstantFuture-class.Rd b/man/ConstantFuture-class.Rd
new file mode 100644
index 0000000..6e3e7b0
--- /dev/null
+++ b/man/ConstantFuture-class.Rd
@@ -0,0 +1,24 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/ConstantFuture-class.R
+\name{ConstantFuture-class}
+\alias{ConstantFuture}
+\alias{ConstantFuture-class}
+\title{A future with a constant value}
+\usage{
+ConstantFuture(expr = NULL, envir = emptyenv(), substitute = FALSE,
+  local = FALSE, gc = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R value.}
+
+\item{\dots}{Not used.}
+}
+\value{
+An object of class \code{ConstantFuture}.
+}
+\description{
+A constant future is a future whose expression is a constant
+and therefore already resolved upon creation
+}
+\keyword{internal}
+
diff --git a/man/EagerFuture-class.Rd b/man/EagerFuture-class.Rd
new file mode 100644
index 0000000..e31e997
--- /dev/null
+++ b/man/EagerFuture-class.Rd
@@ -0,0 +1,39 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/EagerFuture-class.R
+\name{EagerFuture-class}
+\alias{EagerFuture}
+\alias{EagerFuture-class}
+\title{An eager future is a future whose value will be resolved immediately}
+\usage{
+EagerFuture(expr = NULL, envir = parent.frame(), substitute = FALSE,
+  local = TRUE, gc = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE).}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{local}{If TRUE, the expression is evaluated such that
+all assignments are done to local temporary environment, otherwise
+the assignments are done in the calling environment.}
+
+\item{gc}{If TRUE, the garbage collector run after the future is resolved.}
+
+\item{\dots}{Additional named elements of the future.}
+}
+\value{
+An object of class \code{EagerFuture}.
+}
+\description{
+An eager future is a future whose value will be resolved immediately
+}
+\seealso{
+To evaluate an expression using "eager future", see function
+\code{\link{eager}()}.
+}
+\keyword{internal}
+
diff --git a/man/Future-class.Rd b/man/Future-class.Rd
new file mode 100644
index 0000000..1d483fa
--- /dev/null
+++ b/man/Future-class.Rd
@@ -0,0 +1,54 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/Future-class.R
+\name{Future-class}
+\alias{Future}
+\alias{Future-class}
+\title{A future represents a value that will be available at some point in the future}
+\usage{
+Future(expr = NULL, envir = parent.frame(), substitute = FALSE,
+  local = TRUE, gc = FALSE, earlySignal = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE).}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{local}{If TRUE, the expression is evaluated such that
+all assignments are done to local temporary environment, otherwise
+the assignments are done in the calling environment.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{earlySignal}{Specified whether conditions should be signaled
+as soon as possible or not.}
+
+\item{\dots}{Additional named elements of the future.}
+}
+\value{
+An object of class \code{Future}.
+}
+\description{
+A \emph{future} is an abstraction for a \emph{value} that may
+available at some point in the future.  A future can either be
+\code{unresolved} or \code{resolved}, a state which can be checked
+with \code{\link{resolved}()}.  As long as it is \emph{unresolved}, the
+value is not available.  As soon as it is \emph{resolved}, the value
+is available via \code{\link[future]{value}()}.
+}
+\details{
+A Future object is itself an \link{environment}.
+}
+\seealso{
+One function that creates a Future is \code{\link{future}()}.
+It returns a Future that evaluates an R expression in the future.
+An alternative approach is to use the \code{\link{\%<=\%}} infix
+assignment operator, which creates a future from the
+right-hand-side (RHS) R expression and assigns its future value
+to a variable as a \emph{\link[base]{promise}}.
+}
+
diff --git a/man/FutureError.Rd b/man/FutureError.Rd
new file mode 100644
index 0000000..a119913
--- /dev/null
+++ b/man/FutureError.Rd
@@ -0,0 +1,26 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/FutureError-class.R
+\name{FutureError}
+\alias{FutureError}
+\alias{getOutput}
+\title{An error occurred while trying to evaluate a future}
+\usage{
+FutureError(message, call = NULL, future = NULL, output = NULL)
+}
+\arguments{
+\item{message}{The error message.}
+
+\item{call}{The call stack that led up to the error.}
+
+\item{future}{The \link{Future} involved.}
+
+\item{output}{Output captured when error occurred.}
+}
+\value{
+An \link[base:conditions]{error} object of class FutureError.
+}
+\description{
+An error occurred while trying to evaluate a future
+}
+\keyword{internal}
+
diff --git a/man/LazyFuture-class.Rd b/man/LazyFuture-class.Rd
new file mode 100644
index 0000000..51359aa
--- /dev/null
+++ b/man/LazyFuture-class.Rd
@@ -0,0 +1,39 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/LazyFuture-class.R
+\name{LazyFuture-class}
+\alias{LazyFuture}
+\alias{LazyFuture-class}
+\title{A lazy future is a future whose value will be resolved at the time when it is requested}
+\usage{
+LazyFuture(expr = NULL, envir = parent.frame(), substitute = FALSE,
+  local = TRUE, gc = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE).}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{local}{If TRUE, the expression is evaluated such that
+all assignments are done to local temporary environment, otherwise
+the assignments are done in the calling environment.}
+
+\item{gc}{If TRUE, the garbage collector run after the future is resolved.}
+
+\item{\dots}{Additional named elements of the future.}
+}
+\value{
+An object of class \code{LazyFuture}.
+}
+\description{
+A lazy future is a future whose value will be resolved at the time when it is requested
+}
+\seealso{
+To evaluate an expression using "lazy future", see function
+\code{\link{lazy}()}.
+}
+\keyword{internal}
+
diff --git a/man/MulticoreFuture-class.Rd b/man/MulticoreFuture-class.Rd
new file mode 100644
index 0000000..ad199ec
--- /dev/null
+++ b/man/MulticoreFuture-class.Rd
@@ -0,0 +1,33 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/MulticoreFuture-class.R
+\name{MulticoreFuture-class}
+\alias{MulticoreFuture}
+\alias{MulticoreFuture-class}
+\title{An multicore future is a future whose value will be resolved asynchroneously in a parallel process}
+\usage{
+MulticoreFuture(expr = NULL, envir = parent.frame(), substitute = FALSE,
+  ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE).}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{\dots}{Additional named elements of the future.}
+}
+\value{
+An object of class \code{MulticoreFuture}.
+}
+\description{
+An multicore future is a future whose value will be resolved asynchroneously in a parallel process
+}
+\seealso{
+To evaluate an expression using "multicore future", see function
+\code{\link{multicore}()}.
+}
+\keyword{internal}
+
diff --git a/man/MultiprocessFuture-class.Rd b/man/MultiprocessFuture-class.Rd
new file mode 100644
index 0000000..544e023
--- /dev/null
+++ b/man/MultiprocessFuture-class.Rd
@@ -0,0 +1,33 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/MultiprocessFuture-class.R
+\name{MultiprocessFuture-class}
+\alias{MultiprocessFuture}
+\alias{MultiprocessFuture-class}
+\title{An multiprocess future is a future whose value will be resolved asynchroneously in a parallel process}
+\usage{
+MultiprocessFuture(expr = NULL, envir = parent.frame(),
+  substitute = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE).}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{\dots}{Additional named elements of the future.}
+}
+\value{
+An object of class \code{MultiprocessFuture}.
+}
+\description{
+An multiprocess future is a future whose value will be resolved asynchroneously in a parallel process
+}
+\seealso{
+To evaluate an expression using "multiprocess future", see function
+\code{\link{multiprocess}()}.
+}
+\keyword{internal}
+
diff --git a/man/UniprocessFuture-class.Rd b/man/UniprocessFuture-class.Rd
new file mode 100644
index 0000000..137a0fe
--- /dev/null
+++ b/man/UniprocessFuture-class.Rd
@@ -0,0 +1,37 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/UniprocessFuture-class.R
+\name{UniprocessFuture-class}
+\alias{UniprocessFuture}
+\alias{UniprocessFuture-class}
+\title{An uniprocess future is a future whose value will be resolved synchroneously in the current process}
+\usage{
+UniprocessFuture(expr = NULL, envir = parent.frame(), substitute = FALSE,
+  local = TRUE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE).}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{local}{If TRUE, the expression is evaluated such that
+all assignments are done to local temporary environment, otherwise
+the assignments are done in the calling environment.}
+
+\item{\dots}{Additional named elements of the future.}
+}
+\value{
+An object of class \code{UniprocessFuture}.
+}
+\description{
+An uniprocess future is a future whose value will be resolved synchroneously in the current process
+}
+\seealso{
+To evaluate an expression using "uniprocess future", see functions
+\code{\link{eager}()} and \code{\link{lazy}()}.
+}
+\keyword{internal}
+
diff --git a/man/availableCores.Rd b/man/availableCores.Rd
new file mode 100644
index 0000000..c625e94
--- /dev/null
+++ b/man/availableCores.Rd
@@ -0,0 +1,82 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/availableCores.R
+\name{availableCores}
+\alias{availableCores}
+\title{Get number of available cores on current machine}
+\usage{
+availableCores(constraints = NULL,
+  methods = getOption("future.availableCores.methods", c("system",
+  "mc.cores+1", "_R_CHECK_LIMIT_CORES_", "Slurm", "PBS", "SGE")),
+  na.rm = TRUE, default = c(current = 1L), which = c("min", "max", "all"))
+}
+\arguments{
+\item{constraints}{An optional character specifying under what
+constraints ("purposes") we are requesting the values.
+For instance, on systems where multicore processing is not supported
+(i.e. Windows), using \code{constrains="multicore"} will force a
+single core to be reported.}
+
+\item{methods}{A character vector specifying how to infer the number
+of available cores.}
+
+\item{na.rm}{If TRUE, only non-missing settings are considered/returned.}
+
+\item{default}{The default number of cores to return if no non-missing
+settings are available.}
+
+\item{which}{A character specifying which settings to return.
+If \code{"min"}, the minimum value is returned.
+If \code{"max"}, the maximum value is returned (be careful!)
+If \code{"all"}, all values are returned.}
+}
+\value{
+Return a positive (>=1) integer.
+If \code{which="all"}, then more than one value may be returned.
+Together with \code{na.rm=FALSE} missing values may also be returned.
+}
+\description{
+The current/main R session counts as one, meaning the minimum
+number of cores available is always at least one.
+}
+\details{
+The following settings ("methods") for inferring the number of cores
+are supported:
+\itemize{
+ \item \code{"system"} -
+   Query \code{\link[parallel]{detectCores}()}.
+ \item \code{"mc.cores+1"} -
+   If available, returns the value of option
+   \code{\link[base:options]{mc.cores}} + 1.
+   Note that \option{mc.cores} is defined as the number of
+   \emph{additional} R processes that can be used in addition to the
+   main R process.  This means that with \code{mc.cores=0} all
+   calculations should be done in the main R process, i.e. we have
+   exactly one core available for our calculations.
+   The \option{mc.cores} option defaults to environment variable
+   \env{MC_CORES} (and is set accordingly when the \pkg{parallel}
+   package is loaded).  The \option{mc.cores} option is used by for
+   instance \code{\link[parallel]{mclapply}()}.
+ \item \code{"PBS"} -
+   Query Torque/PBS environment variable \env{PBS_NUM_PPN}.
+   Depending on PBS system configuration, this \emph{resource} parameter
+   may or may not default to one.  It can be specified when submitting
+   a job as in, for instance, \code{qsub -l nodes=4:ppn=2}, which
+   requests four nodes each with two cores.
+ \item \code{"SGE"} -
+   Query Sun/Oracle Grid Engine (SGE) environment variable
+   \env{NSLOTS}.
+   It can be specified when submitting a job as in, for instance,
+   \code{qsub -pe by_node 2}, which two cores on a single machine.
+ \item \code{"Slurm"} -
+   Query Simple Linux Utility for Resource Management (Slurm)
+   environment variable \env{SLURM_CPUS_PER_TASK}.
+   This may or may not be set.  It can be set when submitting a job,
+   e.g. \code{sbatch --cpus-per-task=2 hello.sh} or by adding
+   \code{#SBATCH --cpus-per-task=2} to the `hello.sh` script.
+}
+For any other value of a \code{methods} element, the R option with the
+same name is queried.  If that is not set, the system environment
+variable is queried.  If neither is set, a missing value is returned.
+}
+\keyword{internal}
+
diff --git a/man/backtrace.Rd b/man/backtrace.Rd
new file mode 100644
index 0000000..4796a0f
--- /dev/null
+++ b/man/backtrace.Rd
@@ -0,0 +1,22 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/backtrace.R
+\name{backtrace}
+\alias{backtrace}
+\title{Back trace the expressions evaluated before a condition was caught}
+\usage{
+backtrace(future, envir = parent.frame(), ...)
+}
+\arguments{
+\item{future}{The future with a caught condition.}
+
+\item{envir}{the environment where to locate the future.}
+
+\item{\dots}{Not used.}
+}
+\value{
+A list of calls.
+}
+\description{
+Back trace the expressions evaluated before a condition was caught
+}
+
diff --git a/man/cluster.Rd b/man/cluster.Rd
new file mode 100644
index 0000000..d7d16c3
--- /dev/null
+++ b/man/cluster.Rd
@@ -0,0 +1,87 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/cluster.R
+\name{cluster}
+\alias{cluster}
+\title{Create a cluster future whose value will be resolved asynchroneously in a parallel process}
+\usage{
+cluster(expr, envir = parent.frame(), substitute = TRUE,
+  persistent = FALSE, workers = NULL, gc = FALSE, earlySignal = FALSE,
+  ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done and from which globals are obtained.}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{persistent}{If FALSE, the evaluation environment is cleared
+from objects prior to the evaluation of the future.}
+
+\item{workers}{A cluster object created by
+\code{\link[parallel]{makeCluster}()}.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{earlySignal}{Specified whether conditions should be signaled as soon as possible or not.}
+
+\item{\dots}{Not used.}
+}
+\value{
+A \link{ClusterFuture}.
+}
+\description{
+A cluster future is a future that uses cluster evaluation,
+which means that its \emph{value is computed and resolved in
+parallel in another process}.
+}
+\details{
+This function will block if all available R cluster nodes are
+occupied and will be unblocked as soon as one of the already
+running cluster futures is resolved.
+
+The preferred way to create an cluster future is not to call
+this function directly, but to register it via
+\code{\link{plan}(cluster)} such that it becomes the default
+mechanism for all futures.  After this \code{\link{future}()}
+and \code{\link{\%<=\%}} will create \emph{cluster futures}.
+}
+\examples{
+## Cluster futures gives an error on R CMD check on
+## Windows (but not Linux or OS X) for unknown reasons.
+## The same code works in package tests.
+\donttest{
+
+## Use cluster futures
+cl <- parallel::makeCluster(2L)
+plan(cluster, workers=cl)
+
+## A global variable
+a <- 0
+
+## Create multicore future (explicitly)
+f <- future({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+
+## A cluster future is evaluated in a separate process.
+## Changing the value of a global variable will not
+## affect the result of the future.
+a <- 7
+print(a)
+
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+
+## CLEANUP
+parallel::stopCluster(cl)
+
+}
+}
+
diff --git a/man/eager.Rd b/man/eager.Rd
new file mode 100644
index 0000000..e0efefd
--- /dev/null
+++ b/man/eager.Rd
@@ -0,0 +1,86 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/eager.R
+\name{eager}
+\alias{eager}
+\alias{transparent}
+\title{Create an eager future whose value will be resolved immediately}
+\usage{
+eager(expr, envir = parent.frame(), substitute = TRUE, globals = TRUE,
+  local = TRUE, gc = FALSE, earlySignal = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE).}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{globals}{If TRUE, global objects are validated at the point
+in time when the future is created (always before it is resolved),
+that is, they identified and located.  If some globals fail to be
+located, an informative error is generated.}
+
+\item{local}{If TRUE, the expression is evaluated such that
+all assignments are done to local temporary environment, otherwise
+the assignments are done in the calling environment.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{earlySignal}{Specified whether conditions should be signaled as soon as possible or not.}
+
+\item{\dots}{Not used.}
+}
+\value{
+An \link{EagerFuture}.
+}
+\description{
+An eager future is a future that uses eager evaluation, which means
+that its \emph{value is computed and resolved immediately}, which is
+how regular expressions are evaluated in R.
+The only difference to R itself is that globals are validated
+by default just as for all other types of futures in this package.
+}
+\details{
+The preferred way to create an eager future is not to call this function
+directly, but to register it via \code{\link{plan}(eager)} such that it
+becomes the default mechanism for all futures.  After this
+\code{\link{future}()} and \code{\link{\%<=\%}} will create
+\emph{eager futures}.
+}
+\section{transparent futures}{
+
+Transparent futures are eager futures configured to emulate how R
+evaluates expressions as far as possible.  For instance, errors and
+warnings are signaled immediately and assignments are done to the
+calling environment (without \code{local()} as default for all other
+types of futures).  This makes transparent futures ideal for
+troubleshooting, especially when there are errors.
+}
+\examples{
+## Use eager futures
+plan(eager)
+
+## A global variable
+a <- 0
+
+## Create eager future (implicitly)
+f <- future({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+
+## Since 'a' is a global variable in _eager_ future 'f',
+## it already has been resolved, and any changes to 'a'
+## at this point will _not_ affect the value of 'f'.
+a <- 7
+print(a)
+
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+}
+
diff --git a/man/future.Rd b/man/future.Rd
new file mode 100644
index 0000000..6b352bd
--- /dev/null
+++ b/man/future.Rd
@@ -0,0 +1,66 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/future.R, R/futureCall.R
+\name{future}
+\alias{future}
+\alias{futureCall}
+\title{Create a future}
+\usage{
+future(expr, envir = parent.frame(), substitute = TRUE,
+  evaluator = plan(), ...)
+
+futureCall(FUN, args = NULL, envir = parent.frame(), evaluator = plan(),
+  ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} from where global
+objects should be identified.  Depending on "evaluator",
+it may also be the environment in which the expression
+is evaluated.}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{evaluator}{The actual function that evaluates
+\code{expr} and returns a future.  The evaluator function
+should accept all the same arguments as this function
+(except \code{evaluator}).}
+
+\item{FUN}{A function object.}
+
+\item{args}{A list of arguments passed to function \code{FUN}.}
+
+\item{\dots}{Additional arguments passed to the "evaluator".}
+}
+\value{
+A \link{Future}.
+}
+\description{
+Creates a future from an expression and returns it.
+The state of the future is either unresolved or resolved.
+When it becomes resolved, at some point in the future,
+its value can be retrieved.
+}
+\examples{
+## Use lazy futures
+plan(lazy)
+
+f <- future({
+  a <- 7
+  b <- 3
+  c <- 2
+  a * b * c
+})
+
+print(resolved(f))
+y <- value(f)
+print(y)
+}
+\seealso{
+It is recommended that the evaluator is \emph{non-blocking}
+(returns immediately), but it is not required.
+The default evaluator function is \code{\link{eager}()},
+but this can be changed via \code{\link{plan}()} function.
+}
+
diff --git a/man/future.options.Rd b/man/future.options.Rd
new file mode 100644
index 0000000..782c522
--- /dev/null
+++ b/man/future.options.Rd
@@ -0,0 +1,80 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/options.R
+\name{future.options}
+\alias{R_FUTURE_CORES}
+\alias{R_FUTURE_PLAN}
+\alias{future.availableCores.methods}
+\alias{future.cmdargs}
+\alias{future.cores}
+\alias{future.debug}
+\alias{future.demo.mandelbrot.nrow}
+\alias{future.demo.mandelbrot.region}
+\alias{future.globals.maxSize}
+\alias{future.globals.method}
+\alias{future.globals.onMissing}
+\alias{future.globals.resolve}
+\alias{future.options}
+\alias{future.plan}
+\alias{future.progress}
+\alias{future.resolve.recursive}
+\alias{future.startup.script}
+\alias{future.wait.alpha}
+\alias{future.wait.interval}
+\alias{future.wait.times}
+\title{Options used for futures}
+\description{
+Below are all \R options that are currently used by the \pkg{future} package and packages enhancing it.\cr
+\cr
+\emph{WARNING: Note that the names and the default values of these options may change in future versions of the package.  Please use with care until further notice.}
+}
+\section{Options for controlling futures}{
+
+\describe{
+ \item{\option{future.plan}:}{Default future strategy plan used unless otherwise specified via \code{\link{plan}()}. This will also be the future plan set when calling \code{plan("default")}.  If not specified, this option may be set when the \pkg{future} package is \emph{loaded} if command-line option \code{--parallel=ncores} (short \code{-p ncores}) is specified; if \code{ncores > 1}, then option \option{future.plan} is set to \code{multiprocess} otherwise \code{eager} (in addition to  [...]
+ \item{\option{future.globals.onMissing}:}{Action to take when non-existing global variables ("globals" or "unknowns") are identified when the future is created.  If \code{"error"}, an error is generated immediately.  If \code{"ignore"}, no action is taken and an attempt to evaluate the future expression will be made.  The latter is useful when there is a risk for false-positive globals being identified, e.g. when future expression contains non-standard evaluation (NSE).  (Default: \code [...]
+ \item{\option{future.globals.method}:}{Method used to identify globals. For details, see \code{\link[globals]{globalsOf}()}. (Default: \code{"ordered"})}
+ \item{\option{future.globals.maxSize}:}{Maximum allowed total size (in bytes) of global variables identified. Used to prevent too large exports. (Default: \code{500*1024^2} = 500 MiB)}
+ \item{\option{future.globals.resolve}:}{If \code{TRUE}, globals that are \code{\link{Future}} objects (typically created as \emph{explicit} futures) will be resolved and have their values (using \code{value()}) collected.  Because searching for unresolved futures among globals (including their content) can be expensive, the default is not to do it and instead leave it to the run-time checks that assert proper ownership when resolving futures and collecting their values. (Default: \code{ [...]
+ \item{\option{future.resolve.recursive}:}{An integer specifying the maximum recursive depth to which futures should be resolved. If negative, nothing is resolved.  If \code{0}, only the future itself is resolved.  If \code{1}, the future and any of its elements that are futures are resolved, and so on. If \code{+Inf}, infinite search depth is used. (Default: \code{0})}
+ \item{\option{future.wait.times}:}{Maximum number of times a future is polled waiting for it to be resolved.}
+ \item{\option{future.wait.interval}:}{Initial interval (in seconds) between polls.}
+ \item{\option{future.wait.alpha}:}{Positive scale factor used to increase the interval after each poll. (Default: \code{0.01})}
+}
+}
+
+\section{Options for debugging futures}{
+
+\describe{
+ \item{\option{future.debug}:}{If \code{TRUE}, extensive debug messages are generated. (Default: \code{FALSE})}
+ \item{\option{future.progress}:}{If \code{TRUE}, progress is displayed while blocked waiting for futures to be resolved. (Default: \code{FALSE})}
+}
+}
+
+\section{Options for controlling package startup}{
+
+\describe{
+ \item{\option{future.startup.script}:}{If \code{FALSE}, any \file{.future.R} startup scripts, which may exist in the current directory and / or the user's home directory, are ignored. Such startup scripts are otherwise sourced when the \pkg{future} package is \emph{attached}. \emph{Importantly}, this option is \emph{always} set to \code{FALSE} if the \pkg{future} package is loaded as part of a future expression being evaluated, e.g. in a background process. In order words, they are sour [...]
+ \item{\option{future.cmdargs}:}{Overrides \code{\link[base]{commandArgs}()} when the \pkg{future} package is \emph{loaded}.}
+}
+}
+
+\section{Options for configurating low-level system behaviors}{
+
+\describe{
+ \item{\option{future.availableCores.methods}:}{Default lookup methods for \code{\link{availableCores}()}. (Default: \code{c("system", "mc.cores+1", "_R_CHECK_LIMIT_CORES_", "Slurm", "PBS", "SGE")})}
+ \item{\option{future.availableCores.system}:}{Number of "system" cores used instead of what is reported by \code{\link{availableCores}(which="system")}. If not specified, this option is set according to system environment variable \env{R_FUTURE_AVAILABLECORES_SYSTEM} when the \pkg{future} package is \emph{loaded}.}
+}
+}
+
+\section{Options for demos}{
+
+\describe{
+ \item{\option{future.demo.mandelbrot.region}:}{Either a named list of \code{\link{mandelbrot}()} arguments or an integer in [1,3] specifying a predefined Mandelbrot region. (Default: \code{1L})}
+ \item{\option{future.demo.mandelbrot.nrow}:}{Number of rows and columns of tiles. (Default: \code{3L})}
+}
+}
+\seealso{
+To set \R options when \R starts (even before the \pkg{future} package is loaded), see the \link[base]{Startup} help page.
+}
+\keyword{internal}
+
diff --git a/man/futureAssign.Rd b/man/futureAssign.Rd
new file mode 100644
index 0000000..039bc78
--- /dev/null
+++ b/man/futureAssign.Rd
@@ -0,0 +1,88 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/futureAssign.R
+\name{futureAssign}
+\alias{\%->\%}
+\alias{\%<-\%}
+\alias{\%<=\%}
+\alias{\%=>\%}
+\alias{futureAssign}
+\title{Create a future and assign its value to a variable as a promise}
+\usage{
+futureAssign(name, value, envir = parent.frame(), assign.env = envir,
+  substitute = TRUE)
+}
+\arguments{
+\item{name}{the name of the variable (and the future) to assign.}
+
+\item{value}{the expression to be evaluated in the future and
+whose value will be assigned to the variable.}
+
+\item{envir}{The environment from which global variables used by
+the expression should be search for.}
+
+\item{assign.env}{The environment to which the variable should
+be assigned.}
+
+\item{substitute}{Controls whether \code{expr} should be
+\code{substitute()}:d or not.}
+}
+\value{
+A \link{Future} invisibly.
+}
+\description{
+Method and infix operators for creating futures and assigning
+their values as variables using \link[base]{promise}s.  Trying
+to access such a "future variable" will correspond to requesting
+the value of the underlying future.  If the the future is already
+resolved at this time, then the value will be available
+instantaneously and the future variable will appear as any other
+variable.  If the future is unresolved, then the current process
+will block until the future is resolved and the value is available.
+}
+\details{
+This function creates a future and a corresponding
+\emph{\link[base]{promise}}, which hold the future's value.
+Both the future and the promise are assigned to environment
+\code{assign.env}.  The name of the promise is given by \code{name}
+and the name of the future is \code{.future_<name>}.
+The future is also returned invisibly.
+}
+\examples{
+## Future assignment via "assign" function
+futureAssign("A", {
+  x <- 3
+  x^2
+})
+cat("Value 'A': ", A, sep="")
+
+
+## Equivalent via infix "assign" operator
+A \%<-\% {
+  x <- 3
+  x^2
+}
+cat("Value 'A': ", A, sep="")
+
+
+## A global variable
+a <- 1
+
+## Three future evaluations
+A \%<-\% { 0.1 }
+B \%<-\% { 0.2 }
+C \%<-\% { z <- a+0.3 }
+
+## Sleep until 'C' is available
+cat("Value 'C': ", C, sep="")
+
+## Sleep until 'A' is available
+cat("Value 'A': ", A, sep="")
+
+## Sleep until 'C' is available
+cat("Value 'B': ", B, sep="")
+}
+\seealso{
+The \code{\link{futureOf}()} function can be used to get the
+Future object of a future variable.
+}
+
diff --git a/man/futureOf.Rd b/man/futureOf.Rd
new file mode 100644
index 0000000..c2bfebc
--- /dev/null
+++ b/man/futureOf.Rd
@@ -0,0 +1,67 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/futureOf.R
+\name{futureOf}
+\alias{futureOf}
+\title{Get the future of a future variable}
+\usage{
+futureOf(var = NULL, envir = parent.frame(), mustExist = TRUE,
+  default = NA, drop = FALSE)
+}
+\arguments{
+\item{var}{the variable.  If NULL, all futures in the
+environment are returned.}
+
+\item{envir}{the environment where to search from.}
+
+\item{mustExist}{If TRUE and the variable does not exists, then
+an informative error is thrown, otherwise NA is returned.}
+
+\item{default}{the default value if future was not found.}
+
+\item{drop}{if TRUE and \code{var} is NULL, then returned list
+only contains futures, otherwise also \code{default} values.}
+}
+\value{
+A \link{Future} (or \code{default}).
+If \code{var} is NULL, then a named list of Future:s are returned.
+}
+\description{
+Get the future of a future variable that has been created directly
+or indirectly via \code{\link{future}()}.
+}
+\examples{
+a \%<-\% { 1 }
+
+f <- futureOf(a)
+print(f)
+
+b \%<-\% { 2 }
+
+f <- futureOf(b)
+print(f)
+
+## All futures
+fs <- futureOf()
+print(fs)
+
+
+## Futures part of environment
+env <- new.env()
+env$c \%<-\% { 3 }
+
+f <- futureOf(env$c)
+print(f)
+
+f2 <- futureOf(c, envir=env)
+print(f2)
+
+f3 <- futureOf("c", envir=env)
+print(f3)
+
+fs <- futureOf(envir=env)
+print(fs)
+
+
+
+}
+
diff --git a/man/futures.Rd b/man/futures.Rd
new file mode 100644
index 0000000..197adea
--- /dev/null
+++ b/man/futures.Rd
@@ -0,0 +1,29 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/futures.R
+\name{futures}
+\alias{futures}
+\title{Gets all futures in an object}
+\usage{
+futures(x, ...)
+}
+\arguments{
+\item{x}{An environment, a list, or a list environment.}
+
+\item{...}{Not used.}
+}
+\value{
+An object of same type as \code{x} and with the same names
+and/or dimensions, if set.
+}
+\description{
+Gets all futures in an environment, a list, or a list environment
+and returns an object of the same class (and dimensions).
+Non-future elements are returned as is.
+}
+\details{
+This function is useful for retrieve futures that were created via
+future assignments (\code{\%<=\%}) and therefore stored as promises.
+This function turns such promises into standard \code{Future}
+objects.
+}
+
diff --git a/man/getExpression.Rd b/man/getExpression.Rd
new file mode 100644
index 0000000..bac6280
--- /dev/null
+++ b/man/getExpression.Rd
@@ -0,0 +1,47 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/Future-class.R
+\name{getExpression}
+\alias{getExpression}
+\alias{getExpression.Future}
+\title{Inject code for the next type of future to use for nested futures}
+\usage{
+getExpression(future, ...)
+}
+\arguments{
+\item{future}{Current future.}
+
+\item{...}{Not used.}
+}
+\value{
+A future expression with code injected to set what
+type of future to use for nested futures, iff any.
+}
+\description{
+Inject code for the next type of future to use for nested futures
+}
+\details{
+If no next future strategy is specified, the default is to
+use \link{eager} futures.  This conservative approach protects
+against spawning off recursive futures by mistake, especially
+\link{multicore} and \link{multisession} ones.
+The default will also set \code{options(mc.cores=0L)}, which
+means that no \emph{additional} R processes may be spawned off
+by functions such as \code{\link[parallel:mclapply]{mclapply}()}
+and friends (*).
+
+Currently it is not possible to specify what type of nested
+futures to be used, meaning the above default will always be
+used.
+See \href{https://github.com/HenrikBengtsson/future/issues/37}{Issue #37}
+for plans on adding support for custom nested future types.
+
+(*) Note that using \code{mc.cores=0} will unfortunately cause
+    \code{mclapply()} and friends to generate an error saying
+    "'mc.cores' must be >= 1".  Ideally those functions should
+    fall back to using the non-multicore alternative in this
+    case, e.g. \code{mclapply(...)} => \code{lapply(...)}.
+    See \url{https://github.com/HenrikBengtsson/Wishlist-for-R/issues/7}
+    for a discussion on this.
+}
+\keyword{internal}
+
diff --git a/man/grapes-plan-grapes.Rd b/man/grapes-plan-grapes.Rd
new file mode 100644
index 0000000..cdc1adb
--- /dev/null
+++ b/man/grapes-plan-grapes.Rd
@@ -0,0 +1,22 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/plan_OP.R
+\name{\%plan\%}
+\alias{\%plan\%}
+\title{Use a specific plan for a future assignment}
+\usage{
+fassignment \%plan\% strategy
+}
+\arguments{
+\item{fassignment}{The future assignment, e.g.
+\code{x \%<=\% \{ expr \}}.}
+
+\item{strategy}{The mechanism for how the future should be
+resolved. See \code{\link{plan}()} for further details.}
+}
+\description{
+Use a specific plan for a future assignment
+}
+\seealso{
+The \code{\link{plan}()} function sets the default plan for all futures.
+}
+
diff --git a/man/grapes-tweak-grapes.Rd b/man/grapes-tweak-grapes.Rd
new file mode 100644
index 0000000..6206212
--- /dev/null
+++ b/man/grapes-tweak-grapes.Rd
@@ -0,0 +1,19 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tweak_OP.R
+\name{\%tweak\%}
+\alias{\%tweak\%}
+\title{Temporarily tweaks the arguments of the current strategy}
+\usage{
+fassignment \%tweak\% tweaks
+}
+\arguments{
+\item{fassignment}{The future assignment, e.g.
+\code{x \%<=\% \{ expr \}}.}
+
+\item{tweaks}{A named list (or vector) with arguments that
+should be changed relative to the current strategy.}
+}
+\description{
+Temporarily tweaks the arguments of the current strategy
+}
+
diff --git a/man/lazy.Rd b/man/lazy.Rd
new file mode 100644
index 0000000..48e709a
--- /dev/null
+++ b/man/lazy.Rd
@@ -0,0 +1,113 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/lazy.R
+\name{lazy}
+\alias{lazy}
+\title{Create a lazy future whose value will be resolved at the time when requested}
+\usage{
+lazy(expr, envir = parent.frame(), substitute = TRUE, globals = TRUE,
+  local = TRUE, gc = FALSE, earlySignal = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done (or inherits from if \code{local} is TRUE)
+and from which globals are obtained.}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{globals}{If TRUE, global objects are resolved ("frozen") at
+the point of time when the future is created, otherwise they are
+resolved when the future is resolved.}
+
+\item{local}{If TRUE, the expression is evaluated such that
+all assignments are done to local temporary environment, otherwise
+the assignments are done in the calling environment.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{earlySignal}{Specified whether conditions should be signaled as soon as possible or not.}
+
+\item{\dots}{Not used.}
+}
+\value{
+A \link{LazyFuture}.
+}
+\description{
+A lazy future is a future that uses lazy evaluation, which means
+that its \emph{value is only computed and resolved at the time when the
+value is requested}.  This means that the future will not be resolved
+if the value is never requested.
+}
+\details{
+The preferred way to create a lazy future is not to call this function
+directly, but to register it via \code{\link{plan}(lazy)} such that it
+becomes the default mechanism for all futures.  After this
+\code{\link{future}()} and \code{\link{\%<=\%}} will create
+\emph{lazy futures}.
+}
+\examples{
+## Use lazy futures
+plan(lazy)
+
+## A global variable
+a <- 0
+
+## Create lazy future (implicitly)
+f <- future({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+
+## Although 'f' is a _lazy_ future and therefore
+## resolved/evaluates the future expression only
+## when the value is requested, any global variables
+## identified in the expression (here 'a') are
+## "frozen" at the time point when the future is
+## created.  Because of this, the 'a' in the
+## the future expression preserved the zero value
+## although we reassign it in the global environment
+a <- 7
+print(a)
+
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+
+
+## Another example illustrating that lazy futures go
+## hand-in-hand with lazy evaluation of arguments
+
+## A function that may or may not touch it's argument
+foo <- function(a, use=FALSE) {
+  cat("foo() called\\n")
+  if (use) cat("a=", a, "\\n", sep="")
+}
+
+## Create a future
+x \%<-\% { cat("Pow!\\n"); 1 }
+
+## Lazy evaluation where argument is not used
+foo(x, use=FALSE)
+# Outputs:
+# foo() called
+
+## Lazy evaluation where argument is used
+## Hint: 'x' will be resolved
+foo(x, use=TRUE)
+# Outputs:
+# foo() called
+# Pow!
+# a=1
+
+## Lazy evaluation where argument is used (again)
+## Hint: 'x' is already resolved
+foo(x, use=TRUE)
+# Outputs:
+# foo() called
+# a=1
+}
+
diff --git a/man/mandelbrot.Rd b/man/mandelbrot.Rd
new file mode 100644
index 0000000..b3bd019
--- /dev/null
+++ b/man/mandelbrot.Rd
@@ -0,0 +1,54 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/mandelbrot.R
+\name{mandelbrot}
+\alias{as.raster.Mandelbrot}
+\alias{mandelbrot}
+\alias{mandelbrotTiles}
+\alias{plot.Mandelbrot}
+\title{Mandelbrot convergence counts}
+\usage{
+mandelbrot(...)
+}
+\arguments{
+\item{Z}{A complex matrix for which convergence
+counts should be calculated.}
+
+\item{xmid, ymid, side, resolution}{Alternative specification of
+the complex plane \code{Z}, where
+\code{mean(Re(Z)) == xmid},
+\code{mean(Im(Z)) == ymid},
+\code{diff(range(Re(Z))) == side},
+\code{diff(range(Im(Z))) == side}, and
+\code{dim(Z) == c(resolution, resolution)}.}
+
+\item{maxIter}{Maximum number of iterations per bin.}
+
+\item{tau}{A threshold; the radius when calling
+divergence (Mod(z) > tau).}
+}
+\value{
+Returns an integer matrix (of class Mandelbrot) with
+non-negative counts.
+}
+\description{
+Mandelbrot convergence counts
+}
+\examples{
+counts <- mandelbrot(xmid=-0.75, ymid=0, side=3)
+str(counts)
+\dontrun{
+plot(counts)
+}
+
+\dontrun{
+demo("mandelbrot", package="future", ask=FALSE)
+}
+
+}
+\author{
+The internal Mandelbrot algorithm was inspired by and
+adopted from similar GPL code of Martin Maechler (available
+from ftp://stat.ethz.ch/U/maechler/R/ on 2005-02-18 [sic!]).
+}
+\keyword{internal}
+
diff --git a/man/multicore.Rd b/man/multicore.Rd
new file mode 100644
index 0000000..c8b78bf
--- /dev/null
+++ b/man/multicore.Rd
@@ -0,0 +1,103 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/multicore.R
+\name{multicore}
+\alias{multicore}
+\title{Create a multicore future whose value will be resolved asynchroneously in a forked parallel process}
+\usage{
+multicore(expr, envir = parent.frame(), substitute = TRUE, globals = TRUE,
+  workers = availableCores(constraints = "multicore"), gc = FALSE,
+  earlySignal = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done and from which globals are obtained.}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{globals}{If TRUE, global objects are validated at the point
+in time when the future is created (always before it is resolved),
+that is, they identified and located.  If some globals fail to be
+located, an informative error is generated.}
+
+\item{workers}{The maximum number of multicore futures that can
+be active at the same time before blocking.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{earlySignal}{Specified whether conditions should be signaled as soon as possible or not.}
+
+\item{\dots}{Not used.}
+}
+\value{
+A \link{MulticoreFuture}
+If \code{workers == 1}, then all processing using done in the
+current/main R session and we therefore fall back to using
+a eager future.  This is also the case whenever multicore
+processing is not supported, e.g. on Windows.
+}
+\description{
+A multicore future is a future that uses multicore evaluation,
+which means that its \emph{value is computed and resolved in
+parallel in another process}.
+}
+\details{
+This function will block if all cores are occupied and
+will be unblocked as soon as one of the already running
+multicore futures is resolved.  For the total number of
+cores available including the current/main R process, see
+\code{\link{availableCores}()}.
+
+Not all systems support multicore futures.  For instance,
+it is not supported on Microsoft Windows.  Trying to create
+multicore futures on non-supported systems will silently
+fall back to using \link{eager} futures, which effectively
+corresponds to a multicore future that can handle one parallel
+process (the current one) before blocking.
+
+The preferred way to create an multicore future is not to call
+this function directly, but to register it via
+\code{\link{plan}(multicore)} such that it becomes the default
+mechanism for all futures.  After this \code{\link{future}()}
+and \code{\link{\%<=\%}} will create \emph{multicore futures}.
+}
+\examples{
+## Use multicore futures
+plan(multicore)
+
+## A global variable
+a <- 0
+
+## Create multicore future (explicitly)
+f <- future({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+
+## A multicore future is evaluated in a separate forked
+## process.  Changing the value of a global variable
+## will not affect the result of the future.
+a <- 7
+print(a)
+
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+}
+\seealso{
+For processing in multiple background R sessions, see
+\link{multisession} futures.
+For multicore processing with fallback to multisession where
+the former is not supported, see \link{multiprocess} futures.
+
+Use \code{\link{availableCores}()} to see the total number of
+cores that are available for the current R session.
+Use \code{\link{availableCores}("multicore") > 1L} to check
+whether multicore futures are supported or not on the current
+system.
+}
+
diff --git a/man/multiprocess.Rd b/man/multiprocess.Rd
new file mode 100644
index 0000000..b99c552
--- /dev/null
+++ b/man/multiprocess.Rd
@@ -0,0 +1,80 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/multiprocess.R
+\name{multiprocess}
+\alias{multiprocess}
+\title{Create a multiprocess future whose value will be resolved asynchroneously using multicore or a multisession evaluation}
+\usage{
+multiprocess(expr, envir = parent.frame(), substitute = TRUE,
+  globals = TRUE, workers = availableCores(), gc = FALSE,
+  earlySignal = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done and from which globals are obtained.}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{globals}{If TRUE, global objects are validated at the point
+in time when the future is created (always before it is resolved),
+that is, they identified and located.  If some globals fail to be
+located, an informative error is generated.}
+
+\item{workers}{The maximum number of multiprocess futures that
+can be active at the same time before blocking.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{earlySignal}{Specified whether conditions should be signaled as soon as possible or not.}
+
+\item{\dots}{Not used.}
+}
+\value{
+A \link{MultiprocessFuture} implemented as either a
+\link{MulticoreFuture} or a \link{MultisessionFuture}.
+}
+\description{
+A multiprocess future is a future that uses \link{multicore} evaluation
+if supported, otherwise it uses \link{multisession} evaluation.
+Regardless, its \emph{value is computed and resolved in
+parallel in another process}.
+}
+\examples{
+## Multiprocess futures gives an error on R CMD check on
+## Windows (but not Linux or OS X) for unknown reasons.
+## The same code works in package tests.
+\donttest{
+
+## Use multiprocess futures
+plan(multiprocess)
+
+## A global variable
+a <- 0
+
+## Create multicore future (explicitly)
+f <- future({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+
+## A multiprocess future is evaluated in a separate R process.
+## Changing the value of a global variable will not affect
+## the result of the future.
+a <- 7
+print(a)
+
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+
+}
+}
+\seealso{
+Internally \code{\link{multicore}()} and \code{\link{multisession}()}
+are used.
+}
+
diff --git a/man/multisession.Rd b/man/multisession.Rd
new file mode 100644
index 0000000..c3468a6
--- /dev/null
+++ b/man/multisession.Rd
@@ -0,0 +1,109 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/multisession.R
+\name{multisession}
+\alias{multisession}
+\title{Create a multisession future whose value will be resolved asynchroneously in a parallel R session}
+\usage{
+multisession(expr, envir = parent.frame(), substitute = TRUE,
+  persistent = FALSE, workers = availableCores(), gc = FALSE,
+  earlySignal = FALSE, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done and from which globals are obtained.}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{persistent}{If FALSE, the evaluation environment is cleared
+from objects prior to the evaluation of the future.}
+
+\item{workers}{The maximum number of multisession futures that
+can be active at the same time before blocking.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{earlySignal}{Specified whether conditions should be signaled as soon as possible or not.}
+
+\item{\dots}{Not used.}
+}
+\value{
+A \link{MultisessionFuture}.
+If \code{workers == 1}, then all processing using done in the
+current/main R session and we therefore fall back to using
+a lazy future.
+}
+\description{
+A multisession future is a future that uses multisession evaluation,
+which means that its \emph{value is computed and resolved in
+parallel in another R session}.
+}
+\details{
+This function will block if all available R session are occupied
+and will be unblocked as soon as one of the already running
+multisession futures is resolved.  For the total number of
+R sessions available including the current/main R process, see
+\code{\link{availableCores}()}.
+
+A multisession future is a special type of cluster future.
+
+The preferred way to create an multisession future is not to call
+this function directly, but to register it via
+\code{\link{plan}(multisession)} such that it becomes the default
+mechanism for all futures.  After this \code{\link{future}()}
+and \code{\link{\%<=\%}} will create \emph{multisession futures}.
+}
+\section{Known issues}{
+
+In the current implementation, \emph{all} background R sessions
+are allocated and launched in the background \emph{as soon as the
+first multisession future is created}. This means that more R
+sessions may be running than what will ever be used.
+The reason for this is that background sessions are currently
+created using \code{\link[parallel:makeCluster]{makeCluster}()},
+which requires that all R sessions are created at once.
+}
+\examples{
+## Multisession futures gives an error on R CMD check on
+## Windows (but not Linux or OS X) for unknown reasons.
+## The same code works in package tests.
+\donttest{
+
+## Use multisession futures
+plan(multisession)
+
+## A global variable
+a <- 0
+
+## Create multicore future (explicitly)
+f <- future({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+
+## A multisession future is evaluated in a separate R session.
+## Changing the value of a global variable will not affect
+## the result of the future.
+a <- 7
+print(a)
+
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+
+}
+}
+\seealso{
+For processing in multiple forked R sessions, see
+\link{multicore} futures.
+For multicore processing with fallback to multisession where
+the former is not supported, see \link{multiprocess} futures.
+
+Use \code{\link{availableCores}()} to see the total number of
+cores that are available for the current R session.
+}
+
diff --git a/man/nbrOfWorkers.Rd b/man/nbrOfWorkers.Rd
new file mode 100644
index 0000000..0ec612d
--- /dev/null
+++ b/man/nbrOfWorkers.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/nbrOfWorkers.R
+\name{nbrOfWorkers}
+\alias{nbrOfWorkers}
+\title{Gets the number of workers}
+\usage{
+nbrOfWorkers(evaluator = NULL)
+}
+\arguments{
+\item{evaluator}{A future evaluator function.
+If NULL (default), the current evaluator as returned
+by \code{\link{plan}()} is used.}
+}
+\value{
+A number in [1,Inf].
+}
+\description{
+Gets the number of workers
+}
+
diff --git a/man/plan.Rd b/man/plan.Rd
new file mode 100644
index 0000000..096a752
--- /dev/null
+++ b/man/plan.Rd
@@ -0,0 +1,143 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/plan.R
+\name{plan}
+\alias{plan}
+\title{Plan how to resolve a future}
+\usage{
+plan(strategy = NULL, ..., substitute = TRUE, .call = TRUE)
+}
+\arguments{
+\item{strategy}{The evaluation function (or name of it) to use
+for resolving a future.  If NULL, then the current strategy is returned.}
+
+\item{substitute}{If TRUE, the \code{strategy} expression is
+\code{substitute()}:d, otherwise not.}
+
+\item{.call}{(internal) Used for recording the call to this function.}
+
+\item{\dots}{Additional arguments overriding the default arguments
+of the evaluation function.}
+}
+\value{
+If a new strategy is chosen, then the previous one is returned
+(invisible), otherwise the current one is returned (visibly).
+}
+\description{
+This function allows you to plan the future, more specifically,
+it specifies how \code{\link{future}()}:s are resolved,
+e.g. sequentially or in parallel.
+}
+\details{
+The default strategy is \code{\link{eager}}, but the default can be
+configured by option \option{future.plan} and, if that is not set,
+system environment variable \env{R_FUTURE_PLAN}.
+To reset the strategy back to the default, use \code{plan("default")}.
+}
+\section{Implemented evaluation strategies}{
+
+\itemize{
+ \item{\code{\link{eager}}:}{
+   Resolves futures sequentially in the current R process.
+ }
+ \item{\code{\link{lazy}}:}{
+   Resolves futures synchronously (sequentially) in the current
+   R process, but only if their values are requested.  Futures for
+   which the values are never requested will not be evaluated.
+ }
+ \item{\code{\link{transparent}}:}{
+   Resolves futures synchronously (sequentially) in the current
+   R process and assignments will be done to the calling environment.
+   Early stopping is enabled by default.
+ }
+ \item{\code{\link{multisession}}:}{
+   Resolves futures asynchronously (in parallel) in separate
+   R sessions running in the background on the same machine.
+ }
+ \item{\code{\link{multicore}}:}{
+   Resolves futures asynchronously (in parallel) in separate
+   \emph{forked} R processes running in the background on
+   the same machine.  Not supported on Windows.
+ }
+ \item{\code{\link{multiprocess}}:}{
+   If multicore evaluation is supported, that will be used,
+ }
+ \item{\code{\link{cluster}}:}{
+   Resolves futures asynchronously (in parallel) in separate
+   R sessions running typically on one or more machines.
+ }
+ \item{\code{\link{remote}}:}{
+   Resolves futures asynchronously in a separate R session
+   running on a separate machine, typically on a different
+   network.
+ }
+}
+
+Other package may provide additional evaluation strategies.
+Notably, the \pkg{future.BatchJobs} package implements a
+type of futures that will be resolved via job schedulers
+that are typically available on high-performance compute
+(HPC) clusters, e.g. LSF, Slurm, TORQUE/PBS, Sun Grid Engine,
+and OpenLava.
+}
+\examples{
+a <- b <- c <- NA_real_
+
+# A lazy future
+plan(lazy)
+f <- future({
+  a <- 7
+  b <- 3
+  c <- 2
+  a * b * c
+})
+y <- value(f)
+print(y)
+str(list(a=a, b=b, c=c)) ## All NAs
+
+
+# An eager future
+plan(eager)
+f <- future({
+  a <- 7
+  b <- 3
+  c <- 2
+  a * b * c
+})
+y <- value(f)
+print(y)
+str(list(a=a, b=b, c=c)) ## All NAs
+
+
+# A multicore future
+plan(multicore)
+f <- future({
+  a <- 7
+  b <- 3
+  c <- 2
+  a * b * c
+})
+y <- value(f)
+print(y)
+str(list(a=a, b=b, c=c)) ## All NAs
+
+
+## Multisession futures gives an error on R CMD check on
+## Windows (but not Linux or OS X) for unknown reasons.
+## The same code works in package tests.
+\donttest{
+
+# A multisession future
+plan(multisession)
+f <- future({
+  a <- 7
+  b <- 3
+  c <- 2
+  a * b * c
+})
+y <- value(f)
+print(y)
+str(list(a=a, b=b, c=c)) ## All NAs
+
+}
+}
+
diff --git a/man/remote.Rd b/man/remote.Rd
new file mode 100644
index 0000000..9547c88
--- /dev/null
+++ b/man/remote.Rd
@@ -0,0 +1,59 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/remote.R
+\name{remote}
+\alias{remote}
+\title{Create a remote future whose value will be resolved asynchroneously in a remote process}
+\usage{
+remote(expr, envir = parent.frame(), substitute = TRUE, persistent = TRUE,
+  workers = NULL, gc = FALSE, earlySignal = FALSE, myip = NULL, ...)
+}
+\arguments{
+\item{expr}{An R \link[base]{expression}.}
+
+\item{envir}{The \link{environment} in which the evaluation
+is done and from which globals are obtained.}
+
+\item{substitute}{If TRUE, argument \code{expr} is
+\code{\link[base]{substitute}()}:ed, otherwise not.}
+
+\item{persistent}{If FALSE, the evaluation environment is cleared
+from objects prior to the evaluation of the future.}
+
+\item{workers}{A cluster object created by
+\code{\link[parallel]{makeCluster}()}.}
+
+\item{gc}{If TRUE, the garbage collector run after the future
+is resolved (in the process that evaluated the future).}
+
+\item{earlySignal}{Specified whether conditions should be signaled as soon as possible or not.}
+
+\item{myip}{The external IP address of this machine.
+If NULL, then it is inferred using an online service (default).}
+
+\item{\dots}{Not used.}
+}
+\value{
+A \link{ClusterFuture}.
+}
+\description{
+A remote future is a future that uses remote cluster evaluation,
+which means that its \emph{value is computed and resolved
+remotely in another process}.
+}
+\details{
+Note that remote futures use \code{persistent=TRUE} by default.
+}
+\examples{
+\dontrun{\donttest{
+
+## Use a remote machine
+plan(remote, workers="remote.server.org")
+
+## Evaluate expression remotely
+host \%<-\% { Sys.info()[["nodename"]] }
+host
+[1] "remote.server.org"
+
+}}
+}
+
diff --git a/man/requestCore.Rd b/man/requestCore.Rd
new file mode 100644
index 0000000..b30c0ed
--- /dev/null
+++ b/man/requestCore.Rd
@@ -0,0 +1,36 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/multicore.R
+\name{requestCore}
+\alias{requestCore}
+\title{Request a core for multicore processing}
+\usage{
+requestCore(await, workers = availableCores(),
+  times = getOption("future.wait.times", 1000),
+  delta = getOption("future.wait.interval", 1),
+  alpha = getOption("future.wait.alpha", 1.01))
+}
+\arguments{
+\item{await}{A function used to try to "collect"
+finished multicore subprocesses.}
+
+\item{workers}{Total number of workers available.}
+
+\item{times}{Then maximum number of times subprocesses
+should be collected before timeout.}
+
+\item{delta}{Then base interval (in seconds) to wait
+between each try.}
+
+\item{alpha}{A multiplicative factor used to increase
+the wait interval after each try.}
+}
+\value{
+Invisible TRUE. If no cores are available after
+        extensive waiting, then a timeout error is thrown.
+}
+\description{
+If no cores are available, the current process
+blocks until a core is available.
+}
+\keyword{internal}
+
diff --git a/man/resolve.Rd b/man/resolve.Rd
new file mode 100644
index 0000000..94ec3f6
--- /dev/null
+++ b/man/resolve.Rd
@@ -0,0 +1,44 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/resolve.R
+\name{resolve}
+\alias{resolve}
+\title{Wait until all existing futures in an environment are resolved}
+\usage{
+resolve(x, idxs = NULL, value = FALSE, recursive = 0, sleep = 1,
+  progress = getOption("future.progress", FALSE), ...)
+}
+\arguments{
+\item{x}{an environment holding futures.}
+
+\item{idxs}{subset of elements to check.}
+
+\item{value}{If TRUE, the values are retrieved, otherwise not.}
+
+\item{recursive}{A non-negative number specifying how deep of
+a recursion should be done.  If TRUE, an infintive recursion
+is used.  If FALSE or zero, no recursion is performed.}
+
+\item{sleep}{Number of seconds to wait before checking
+if futures have been resolved since last time.}
+
+\item{progress}{If TRUE textual progress summary is outputted.
+If a function, the it is called as \code{progress(done, total)}
+every time a future is resolved.}
+
+\item{...}{Not used}
+}
+\value{
+Returns \code{x} (regardless of subsetting or not).
+}
+\description{
+The environment is first scanned for futures and then the futures
+are polled until all are resolved.  When a resolved future is
+detected its value is retrieved (optionally).
+This provides an efficient mechanism for waiting for a set of
+futures to be resolved and in the meanwhile retrieving values
+of already resolved futures.
+}
+\seealso{
+futureOf
+}
+
diff --git a/man/resolved.Rd b/man/resolved.Rd
new file mode 100644
index 0000000..4c3b03a
--- /dev/null
+++ b/man/resolved.Rd
@@ -0,0 +1,32 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/resolved.R
+\name{resolved}
+\alias{resolved}
+\alias{resolved.default}
+\title{Check whether a future is resolved or not}
+\usage{
+resolved(x, ...)
+}
+\arguments{
+\item{x}{A \link{Future}, a list or an environment (which also
+includes \link[listenv:listenv]{list environment}.}
+
+\item{\dots}{Not used}
+}
+\value{
+A logical of the same length and dimensions as \code{x}.
+Each element is TRUE unless the corresponding element is a
+non-resolved future in case it is FALSE.
+}
+\description{
+Check whether a future is resolved or not
+}
+\details{
+This method needs to be implemented by the class that implement
+the Future API.  The implementation must never throw an error,
+but only return either TRUE or FALSE.
+It should also be possible to use the method for polling the
+future until it is resolved (without having to wait infinitly long),
+e.g. \code{while (!resolved(future)) Sys.sleep(5)}.
+}
+
diff --git a/man/supportsMulticore.Rd b/man/supportsMulticore.Rd
new file mode 100644
index 0000000..8d6afd9
--- /dev/null
+++ b/man/supportsMulticore.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/availableCores.R
+\name{supportsMulticore}
+\alias{supportsMulticore}
+\title{Check whether multicore processing is supported or not}
+\usage{
+supportsMulticore()
+}
+\value{
+TRUE if multicore processing is supported, otherwise FALSE.
+}
+\description{
+Multicore futures are only supported on systems supporting
+multicore processing.  R supports this on most systems,
+except on Microsoft Windows.
+}
+\seealso{
+To use multicore futures, use \code{\link{plan}(\link{multicore})}.
+}
+
diff --git a/man/tweak.Rd b/man/tweak.Rd
new file mode 100644
index 0000000..fd402e5
--- /dev/null
+++ b/man/tweak.Rd
@@ -0,0 +1,28 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tweak.R
+\name{tweak}
+\alias{tweak}
+\title{Tweaks a future function by adjusting its default arguments}
+\usage{
+tweak(strategy, ..., penvir = parent.frame())
+}
+\arguments{
+\item{strategy}{An existing future function or the name of one.}
+
+\item{...}{Named arguments to replace the defaults of existing
+arguments.}
+
+\item{penvir}{The environment used when searching for a future
+function by its name.}
+}
+\value{
+a future function.
+}
+\description{
+Tweaks a future function by adjusting its default arguments
+}
+\seealso{
+Use \code{\link{plan}()} to set a future to become the
+new default strategy.
+}
+
diff --git a/man/usedCores.Rd b/man/usedCores.Rd
new file mode 100644
index 0000000..4a56d94
--- /dev/null
+++ b/man/usedCores.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/multicore.R
+\name{usedCores}
+\alias{usedCores}
+\title{Get number of cores currently used}
+\usage{
+usedCores()
+}
+\value{
+A positive integer equal or greater than one.
+}
+\description{
+Get number of children plus one (for the current process)
+used by the current R session.  The number of children
+is the total number of subprocesses launched by this
+process that are still running and whose values have yet
+not been collected.
+}
+\keyword{internal}
+
diff --git a/man/value.Rd b/man/value.Rd
new file mode 100644
index 0000000..04aa3b7
--- /dev/null
+++ b/man/value.Rd
@@ -0,0 +1,29 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/Future-class.R
+\name{value.Future}
+\alias{value}
+\alias{value.Future}
+\title{The value of a future}
+\usage{
+\method{value}{Future}(future, signal = TRUE, ...)
+}
+\arguments{
+\item{future}{A \link{Future}.}
+
+\item{signal}{A logical specifying whether (\link[base]{conditions})
+should signaled or be returned as values.}
+
+\item{\dots}{Not used.}
+}
+\value{
+An R object of any data type.
+}
+\description{
+Gets the value of a future.  If the future is unresolved, then
+the evaluation blocks until the future is resolved.
+}
+\details{
+This method needs to be implemented by the class that implement
+the Future API.
+}
+
diff --git a/man/values.Rd b/man/values.Rd
new file mode 100644
index 0000000..128be90
--- /dev/null
+++ b/man/values.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/values.R
+\name{values}
+\alias{values}
+\title{Gets all values in an object}
+\usage{
+values(x, ...)
+}
+\arguments{
+\item{x}{An environment, a list, or a list environment.}
+
+\item{...}{Additional arguments passed to \code{value()} of each future.}
+}
+\value{
+An object of same type as \code{x} and with the same names
+and/or dimensions, if set.
+}
+\description{
+Gets all values in an environment, a list, or a list environment
+and returns an object of the same class (and dimensions).
+All future elements are replaced by their corresponding
+\code{value()} values.  For all other elements, the existing
+object is kept.
+}
+
diff --git a/tests/ClusterRegistry.R b/tests/ClusterRegistry.R
new file mode 100644
index 0000000..c6ec62a
--- /dev/null
+++ b/tests/ClusterRegistry.R
@@ -0,0 +1,46 @@
+source("incl/start.R")
+
+message("*** ClusterRegistry() ... ")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  message("Available cores: ", availableCores())
+
+  ## In case sessions have been created in previous tests
+  ClusterRegistry("stop")
+
+  res <- try({
+    cluster <- ClusterRegistry("set", workers=availableCores()-1L)
+    print(cluster)
+  }, silent=TRUE)
+  if (cores == 1) stopifnot(inherits(res, "try-error"))
+
+  cluster <- ClusterRegistry(action="start", workers=1L)
+  print(cluster)
+  stopifnot(length(cluster) == 1L)
+
+  cluster <- ClusterRegistry(action="get")
+  print(cluster)
+  stopifnot(length(cluster) == 1L)
+
+  cluster <- ClusterRegistry(action="stop")
+  print(cluster)
+  stopifnot(length(cluster) == 0L)
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+
+message("*** ClusterRegistry() - exceptions ...")
+
+res <- try(ClusterRegistry(action="start", workers=TRUE))
+stopifnot(inherits(res, "try-error"))
+
+message("*** ClusterRegistry() - exceptions ... DONE")
+
+
+message("*** ClusterRegistry() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/Future-class.R b/tests/Future-class.R
new file mode 100644
index 0000000..158ff83
--- /dev/null
+++ b/tests/Future-class.R
@@ -0,0 +1,29 @@
+source("incl/start.R")
+
+message("*** Future class ...")
+
+message("*** Future class - exception ...")
+
+f <- Future()
+print(f)
+res <- try(value(f), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+## values() is an alias for value() for Future
+res <- try(values(f), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+## When no packages are exported
+foo <- structure(function(...) { Future(1) }, class="future")
+plan(foo)
+f <- Future()
+expr <- getExpression(f)
+print(expr)
+stopifnot(is.call(expr))
+
+message("*** Future class - exception ... DONE")
+
+message("*** Future class ... DONE")
+
+source("incl/end.R")
diff --git a/tests/FutureError.R b/tests/FutureError.R
new file mode 100644
index 0000000..7441fd2
--- /dev/null
+++ b/tests/FutureError.R
@@ -0,0 +1,37 @@
+source("incl/start.R")
+
+message("*** FutureError class ...")
+
+## Minimal
+ex <- FutureError(message="Woops")
+print(ex)
+
+f <- future({ 42L; stop("XXX") })
+v <- value(f, signal=FALSE)
+print(v)
+ex <- FutureError(message="Woops", future=f, output=c("Darn", "it"))
+print(ex)
+
+res <- getOutput(ex)
+print(res)
+stopifnot(all(res == c("Darn", "it")))
+
+res <- getOutput(ex, head=1L)
+print(res)
+stopifnot(res == "Darn")
+
+res <- getOutput(ex, tail=1L)
+print(res)
+stopifnot(res == "it")
+
+res <- getOutput(ex, head=1L, tail=1L)
+print(res)
+stopifnot(res == c("Darn", "it"))
+
+res <- getOutput(ex, collapse="\n")
+print(res)
+stopifnot(res == "Darn\nit")
+
+message("*** FutureError class ... DONE")
+
+source("incl/end.R")
diff --git a/tests/FutureRegistry.R b/tests/FutureRegistry.R
new file mode 100644
index 0000000..82d98de
--- /dev/null
+++ b/tests/FutureRegistry.R
@@ -0,0 +1,107 @@
+source("incl/start.R")
+
+message("*** FutureRegistry() ...")
+
+for (where in c("multicore", "rscript")) {
+  message(sprintf("*** FutureRegistry('%s', 'list') ...", where))
+  futures <- FutureRegistry(where, action="list")
+  print(futures)
+  stopifnot(length(futures) == 0L)
+
+
+  message(sprintf("*** FutureRegistry('%s', 'add') ...", where))
+  f <- future({ 1 })
+  print(f)
+  FutureRegistry(where, action="add", future=f)
+
+
+  message(sprintf("*** FutureRegistry('%s', 'list') ...", where))
+  futures <- FutureRegistry(where, action="list")
+  print(futures)
+  stopifnot(length(futures) == 1L)
+
+
+  message(sprintf("*** FutureRegistry('%s', 'remove') ...", where))
+  FutureRegistry(where, action="remove", future=f)
+
+
+  message(sprintf("*** FutureRegistry('%s', 'list') ...", where))
+  futures <- FutureRegistry(where, action="list")
+  print(futures)
+  stopifnot(length(futures) == 0L)
+
+
+  message(sprintf("*** FutureRegistry('%s', 'add') ...", where))
+  f <- future({ 2 })
+  print(f)
+  FutureRegistry(where, action="add", future=f)
+
+
+  message(sprintf("*** FutureRegistry('%s', 'list') ...", where))
+  futures <- FutureRegistry(where, action="list")
+  print(futures)
+  stopifnot(length(futures) == 1L)
+
+
+  message(sprintf("*** FutureRegistry('%s', 'collect-first') ...", where))
+  FutureRegistry(where, action="collect-first")
+
+  futures <- FutureRegistry(where, action="list")
+  print(futures)
+  stopifnot(length(futures) < 1L)
+
+  message(sprintf("*** FutureRegistry('%s', 'add') ...", where))
+  f <- future({ 2 })
+  print(f)
+  FutureRegistry(where, action="add", future=f)
+
+
+  message(sprintf("*** FutureRegistry('%s', 'reset') ...", where))
+  FutureRegistry(where, action="reset")
+
+
+  message(sprintf("*** FutureRegistry('%s', 'list') ...", where))
+  futures <- FutureRegistry(where, action="list")
+  print(futures)
+  stopifnot(length(futures) == 0L)
+}
+
+
+message("*** FutureRegistry() - exceptions ...")
+
+futures <- FutureRegistry(where="test", action="list")
+stopifnot(length(futures) == 0)
+
+f <- future(1)
+FutureRegistry(where="test", action="add", future=f)
+futures <- FutureRegistry(where="test", action="list")
+stopifnot(length(futures) == 1)
+
+res <- try(FutureRegistry(where="test", action="add", future=f), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+futures <- FutureRegistry(where="test", action="list")
+stopifnot(length(futures) == 1)
+
+
+FutureRegistry(where="test", action="remove", future=f)
+futures <- FutureRegistry(where="test", action="list")
+stopifnot(length(futures) == 0)
+
+res <- try(FutureRegistry(where="test", action="remove", future=f), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+futures <- FutureRegistry(where="test", action="list")
+stopifnot(length(futures) == 0)
+
+FutureRegistry(where="test", action="reset")
+futures <- FutureRegistry(where="test", action="list")
+stopifnot(length(futures) == 0)
+
+res <- try(FutureRegistry(where="test", action="<unknown>"), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** FutureRegistry() - exceptions ... DONE")
+
+
+message("*** FutureRegistry() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/availableCores.R b/tests/availableCores.R
new file mode 100644
index 0000000..9a53bdf
--- /dev/null
+++ b/tests/availableCores.R
@@ -0,0 +1,77 @@
+source("incl/start.R")
+
+message("*** availableCores() ...")
+
+## detectCores() may return NA_integer_
+n <- parallel::detectCores()
+message(sprintf("detectCores()=%d", n))
+stopifnot(length(n) == 1, is.numeric(n))
+
+## Default
+print(availableCores())
+
+n <- availableCores()
+message(sprintf("availableCores()=%d", n))
+stopifnot(length(n) == 1, is.numeric(n), n >= 1)
+
+## Minimium of all known settings (default)
+print(availableCores(which="min"))
+
+## Maximum of all known settings (should never be used)
+print(availableCores(which="max"))
+
+## All known settings
+print(availableCores(na.rm=FALSE, which="all"))
+
+## System settings
+n <- availableCores(methods="system")
+print(n)
+stopifnot(length(n) == 1, is.numeric(n), is.finite(n), n >= 1)
+
+## Predefined ones for known cluster schedulers
+print(availableCores(methods="PBS"))
+print(availableCores(methods="SGE"))
+print(availableCores(methods="Slurm"))
+
+## Any R options and system environment variable
+print(availableCores(methods=c("width", "FOO_BAR_ENV"),
+                     na.rm=FALSE, which="all"))
+
+## Exception handling
+Sys.setenv("FOO_BAR_ENV"="0")
+res <- try(availableCores(methods="FOO_BAR_ENV"), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+
+## Deprecated
+res <- tryCatch(availableCores(methods="mc.cores"), warning=function(w) w)
+print(res)
+stopifnot(inherits(res, "warning"))
+
+
+message("*** Internal detectCores() ...")
+
+## Option 'future.availableCores.system'
+env <- environment(future:::detectCores)
+env$res <- NULL
+options(future.availableCores.system=2L)
+n <- detectCores()
+print(n)
+stopifnot(is.integer(n), is.finite(n), n >= 1, n == 2L)
+options(future.availableCores.system=NULL)
+
+## Reset
+env <- environment(future:::detectCores)
+env$res <- NULL
+n <- detectCores()
+print(n)
+stopifnot(is.integer(n), is.finite(n), n >= 1)
+
+
+message("*** Internal detectCores() ... DONE")
+
+
+message("*** availableCores() ... DONE")
+
+source("incl/end.R")
+
diff --git a/tests/backtrace.R b/tests/backtrace.R
new file mode 100644
index 0000000..da9bec0
--- /dev/null
+++ b/tests/backtrace.R
@@ -0,0 +1,55 @@
+source("incl/start.R")
+
+message("*** backtrace( ) ...")
+
+message("*** backtrace( ) - explicit future ...")
+
+f <- future({ 42L; stop("Woops") })
+v <- value(f, signal=FALSE)
+print(v)
+calls <- backtrace(f)
+print(calls)
+
+message("*** backtrace( ) - explicit future ... DONE")
+
+
+message("*** backtrace( ) - implicit future ...")
+
+v %<-% { 42L; stop("Woops") }
+calls <- backtrace(v)
+print(calls)
+
+message("*** backtrace( ) - implicit future ... DONE")
+
+
+message("*** backtrace( ) - exceptions ...")
+
+message("- No condition ...")
+f <- future(42L)
+res <- try(backtrace(f), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+message("- No call stack ...")
+f <- future({ 42L; stop("Woops") })
+v <- value(f, signal=FALSE)
+f$value$traceback <- NULL ## Remove call stack
+res <- try(backtrace(f), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+if (availableCores() >= 2L) {
+  message("- Non-resolved future ...")
+  plan(multiprocess, workers=2L)
+  f <- future({ Sys.sleep(10); 42L; stop("Woops") })
+  res <- try(backtrace(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+}
+
+message("*** backtrace( ) - exceptions ... DONE")
+
+
+message("*** backtrace( ) ... DONE")
+
+source("incl/end.R")
diff --git a/tests/cluster.R b/tests/cluster.R
new file mode 100644
index 0000000..8419d12
--- /dev/null
+++ b/tests/cluster.R
@@ -0,0 +1,191 @@
+source("incl/start.R")
+library("listenv")
+
+message("*** cluster() ...")
+
+message("Cluster type: ", parallel:::getClusterOption("type"))
+message("Library paths: ", paste(sQuote(.libPaths()), collapse=", "))
+message("Package path: ", sQuote(system.file(package="future")))
+
+for (cores in 1:2) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  ## Set up a cluster with 4 nodes (explicitly)
+  cl <- parallel::makeCluster(cores)
+  plan(cluster, workers=cl)
+
+  ## No global variables
+  f <- try(cluster({
+    42L
+  }, workers=cl), silent=FALSE)
+  print(f)
+  stopifnot(inherits(f, "ClusterFuture"))
+
+  print(resolved(f))
+  y <- value(f)
+  print(y)
+  stopifnot(y == 42L)
+
+
+  ## Set up a cluster with 4 nodes (implicitly)
+  plan(cluster, workers=cores)
+
+  ## No global variables
+  f <- try(cluster({
+    42L
+  }, workers=cl), silent=FALSE)
+  print(f)
+  stopifnot(inherits(f, "ClusterFuture"))
+
+  print(resolved(f))
+  y <- value(f)
+  print(y)
+  stopifnot(y == 42L)
+
+
+  ## A global variable
+  a <- 0
+  f <- try(future({
+    b <- 3
+    c <- 2
+    a * b * c
+  }))
+  print(f)
+
+
+  ## A cluster future is evaluated in a separate
+  ## R session process.  Changing the value of a global
+  ## variable should not affect the result of the
+  ## future.
+  a <- 7  ## Make sure globals are frozen
+  v <- value(f)
+  print(v)
+  stopifnot(v == 0)
+
+
+  message("*** cluster() with globals and blocking")
+  x <- listenv()
+  for (ii in 1:4) {
+    message(sprintf(" - Creating cluster future #%d ...", ii))
+    x[[ii]] <- future({ ii })
+  }
+  message(sprintf(" - Resolving %d cluster futures", length(x)))
+  v <- sapply(x, FUN=value)
+  stopifnot(all(v == 1:4))
+
+
+  message("*** cluster() and errors")
+  f <- future({
+    stop("Whoops!")
+    1
+  })
+  print(f)
+  v <- value(f, signal=FALSE)
+  print(v)
+  stopifnot(inherits(v, "simpleError"))
+
+  res <- try(value(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+
+  ## Error is repeated
+  res <- try(value(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+
+
+  message("*** cluster() - too large globals ...")
+  ooptsT <- options(future.globals.maxSize=1024*4L)
+
+  limit <- getOption("future.globals.maxSize")
+  cat(sprintf("Max total size of globals: %g bytes\n", limit))
+
+  ## A large object
+  a <- 1:1014
+  yTruth <- sum(a)
+  size <- object.size(a)
+  cat(sprintf("a: %g bytes\n", size))
+  f <- future({ sum(a) })
+  print(f)
+  rm(list="a")
+  v <- value(f)
+  print(v)
+  stopifnot(v == yTruth)
+
+
+  ## A too large object
+  a <- 1:1019 ## also on 32-bit platforms
+  yTruth <- sum(a)
+  size <- object.size(a)
+  cat(sprintf("a: %g bytes\n", size))
+  res <- try(f <- future({ sum(a) }), silent=TRUE)
+  rm(list="a")
+  stopifnot(inherits(res, "try-error"))
+
+  ## Undo options changed in this test
+  options(ooptsT)
+
+  message("*** cluster() - too large globals ... DONE")
+
+  message("*** cluster() - installed packages ...")
+  f <- try(cluster({
+    list(
+      libPaths = .libPaths(),
+      pkgs     = installed.packages()
+    )
+  }, workers=cl), silent=FALSE)
+  print(f)
+  stopifnot(inherits(f, "ClusterFuture"))
+  v <- value(f)
+  message(paste(capture.output(str(v)), collapse="\n"))
+  message("*** cluster() - installed packages ... DONE")
+
+
+  message("*** cluster() - assert covr workaround ...")
+  f <- try(cluster({
+    future:::hpaste(1:100)
+  }, workers=cl), silent=FALSE)
+  print(f)
+  stopifnot(inherits(f, "ClusterFuture"))
+  v <- value(f)
+  message(v)
+  stopifnot(v == hpaste(1:100))
+  message("*** cluster() - assert covr workaround ... DONE")
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+
+message("*** cluster() - setDefaultCluster() ...")
+
+library("parallel")
+setDefaultCluster(makeCluster(2))
+plan(cluster)
+
+pid <- Sys.getpid()
+message(pid)
+
+a %<-% Sys.getpid()
+b %<-% Sys.getpid()
+message(a)
+message(b)
+
+setDefaultCluster(NULL)
+
+message("*** cluster() - setDefaultCluster() ... DONE")
+
+
+message("*** cluster() - exceptions ...")
+
+res <- try(cluster(42L, workers=NA), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** cluster() - exceptions ... DONE")
+
+
+message("*** cluster() ... DONE")
+
+## Cleanup
+parallel::stopCluster(cl)
+source("incl/end.R")
diff --git a/tests/constant.R b/tests/constant.R
new file mode 100644
index 0000000..710f971
--- /dev/null
+++ b/tests/constant.R
@@ -0,0 +1,30 @@
+source("incl/start.R")
+library("listenv")
+
+message("*** constant() ...")
+
+## No global variables
+f <- try(constant(42L), silent=FALSE)
+print(f)
+stopifnot(inherits(f, "ConstantFuture"))
+
+print(resolved(f))
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+plan(constant)
+## No global variables
+f <- try(future(42L), silent=FALSE)
+print(f)
+stopifnot(inherits(f, "ConstantFuture"))
+
+print(resolved(f))
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+message("*** constant() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/demo.R b/tests/demo.R
new file mode 100644
index 0000000..e242c0d
--- /dev/null
+++ b/tests/demo.R
@@ -0,0 +1,29 @@
+source("incl/start.R")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  options("R_FUTURE_DEMO_MANDELBROT_PLANES"=4L)
+
+  message("*** Demos ...")
+
+  message("*** Mandelbrot demo of the 'future' package ...")
+
+  if (getRversion() >= "3.2.0") {
+    for (strategy in supportedStrategies()) {
+      message(sprintf("- plan('%s') ...", strategy))
+      plan(strategy)
+      demo("mandelbrot", package="future", ask=FALSE)
+      message(sprintf("- plan('%s') ... DONE", strategy))
+    }
+  } else {
+    message(" - This demo requires R (>= 3.2.0). Skipping test.")
+  }
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** Demos ... DONE")
+
+source("incl/end.R")
diff --git a/tests/deprecated.R b/tests/deprecated.R
new file mode 100644
index 0000000..9307aef
--- /dev/null
+++ b/tests/deprecated.R
@@ -0,0 +1,64 @@
+source("incl/start.R")
+
+message("*** Deprecated API ...")
+
+message("*** Deprecated arguments ...")
+
+res <- tryCatch({
+  f <- ClusterFuture(42L, cluster="localhost")
+}, warning = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+res <- tryCatch({
+  f <- cluster(42L, cluster="localhost")
+}, warning = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+res <- tryCatch({
+  f <- multicore(42L, maxCores=2L)
+}, warning = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+res <- tryCatch({
+  f <- multisession(42L, maxCores=2L)
+}, warning = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+res <- tryCatch({
+  f <- multiprocess(42L, maxCores=2L)
+}, warning = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+res <- tryCatch({
+  s <- tweak(multiprocess, maxCores=2L)
+}, warning = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+res <- tryCatch({
+  s <- tweak(cluster, cluster="localhost")
+}, warning = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+message("*** Deprecated arguments ... DONE")
+
+
+message("*** Deprecated argument values ...")
+
+res <- tryCatch({
+  n <- availableCores(methods="mc.cores")
+}, warning = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+message("*** Deprecated argument values ... DONE")
+
+
+message("*** Deprecated API ... DONE")
+
+
+message("*** Defunct API ...")
+
+
+message("*** Defunct API ... DONE")
+
+
+source("incl/end.R")
diff --git a/tests/dotdotdot.R b/tests/dotdotdot.R
new file mode 100644
index 0000000..7e16c33
--- /dev/null
+++ b/tests/dotdotdot.R
@@ -0,0 +1,64 @@
+source("incl/start.R")
+library("listenv")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  message("*** Global argument '...' in lazy futures ...")
+
+  sum_fcns <- list()
+
+  sum_fcns$A <- function(x, ...) {
+    message("Arguments '...' exists: ", exists("...", inherits=TRUE))
+    y %<-% { sum(x, ...) }
+    y
+  }
+
+
+  sum_fcns$B <- function(x, ...) {
+    sumt <- function(x) {
+      message("Arguments '...' exists: ", exists("...", inherits=TRUE))
+      y %<-% { sum(x, ...) }
+      y
+    }
+    sumt(x)
+  }
+
+  sum_fcns$C <- function(x, y) {
+    message("Arguments '...' exists: ", exists("...", inherits=TRUE))
+    y %<-% { sum(x, y) }
+    y
+  }
+
+  sum_fcns$D <- function(x, y) {
+    message("Arguments '...' exists: ", exists("...", inherits=TRUE))
+    y %<-% { sum(x, y, ...) }
+    y
+  }
+
+
+  for (strategy in supportedStrategies()) {
+    message(sprintf("- plan('%s') ...", strategy))
+    plan(strategy, substitute=FALSE)
+
+    for (name in names(sum_fcns)) {
+      message(sprintf("** Sum function '%s' with plan('%s') ...", name, strategy))
+      sum_fcn <- sum_fcns[[name]]
+      print(sum_fcn)
+      y <- try(sum_fcn(1:2,3))
+      print(y)
+      if (name %in% c("D")) {
+        stopifnot(inherits(y, "try-error"))
+      } else {
+        stopifnot(y == 6)
+      }
+    }
+  }
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** Global argument '...' in lazy futures ... DONE")
+
+source("incl/end.R")
diff --git a/tests/eager.R b/tests/eager.R
new file mode 100644
index 0000000..451278e
--- /dev/null
+++ b/tests/eager.R
@@ -0,0 +1,62 @@
+source("incl/start.R")
+
+message("*** eager() ...")
+
+for (globals in c(FALSE, TRUE)) {
+
+message(sprintf("*** eager(..., globals=%s) without globals", globals))
+
+f <- eager({
+  42L
+}, globals=globals)
+stopifnot(inherits(f, "EagerFuture"))
+
+print(resolved(f))
+stopifnot(resolved(f))
+
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+message(sprintf("*** eager(..., globals=%s) with globals", globals))
+## A global variable
+a <- 0
+f <- eager({
+  b <- 3
+  c <- 2
+  a * b * c
+}, globals=globals)
+print(f)
+
+## Since 'a' is a global variable in _eager_ future 'f',
+## it already has been resolved, and any changes to 'a'
+## at this point will _not_ affect the value of 'f'.
+a <- 7
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+
+
+message(sprintf("*** eager(..., globals=%s) and errors", globals))
+f <- eager({
+  stop("Whoops!")
+  1
+}, globals=globals)
+print(f)
+stopifnot(inherits(f, "EagerFuture"))
+
+res <- try(value(f), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+## Error is repeated
+res <- try(value(f), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+} # for (globals ...)
+
+message("*** eager() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/early-signaling.R b/tests/early-signaling.R
new file mode 100644
index 0000000..6caee07
--- /dev/null
+++ b/tests/early-signaling.R
@@ -0,0 +1,108 @@
+source("incl/start.R")
+
+options(future.debug=FALSE)
+
+message("*** Early signaling of conditions ...")
+
+message("*** Early signaling of conditions with eager futures ...")
+
+plan(eager)
+f <- future({ stop("bang!") })
+r <- resolved(f)
+stopifnot(r)
+v <- try(value(f), silent=TRUE)
+stopifnot(inherits(v, "try-error"))
+
+plan(eager, earlySignal=TRUE)
+f <- try(future({ stop("bang!") }), silent=TRUE)
+stopifnot(inherits(f, "try-error"))
+
+message("*** Early signaling of conditions with eager futures ... DONE")
+
+
+message("*** Early signaling of conditions with lazy futures ...")
+
+plan(lazy)
+f <- future({ stop("bang!") })
+r <- resolved(f)
+stopifnot(r)
+v <- try(value(f), silent=TRUE)
+stopifnot(inherits(v, "try-error"))
+
+plan(lazy, earlySignal=TRUE)
+
+## Errors
+f <- future({ stop("bang!") })
+r <- try(resolved(f), silent=TRUE)
+stopifnot(inherits(r, "try-error"))
+v <- try(value(f), silent=TRUE)
+stopifnot(inherits(v, "try-error"))
+
+## Warnings
+f <- future({ warning("careful!") })
+res <- tryCatch({
+  r <- resolved(f)
+}, condition = function(w) w)
+stopifnot(inherits(res, "warning"))
+
+## Messages
+f <- future({ message("hey!") })
+res <- tryCatch({
+  r <- resolved(f)
+}, condition = function(w) w)
+stopifnot(inherits(res, "message"))
+
+## Condition
+f <- future({ signalCondition(simpleCondition("hmm")) })
+res <- tryCatch({
+  r <- resolved(f)
+}, condition = function(w) w)
+stopifnot(inherits(res, "condition"))
+
+message("*** Early signaling of conditions with lazy futures ... DONE")
+
+message("Number of available cores: ", availableCores())
+
+message("*** Early signaling of conditions with multisession futures ...")
+
+plan(multisession)
+f <- future({ stop("bang!") })
+r <- resolved(f)
+stopifnot(r)
+v <- try(value(f), silent=TRUE)
+stopifnot(inherits(v, "try-error"))
+
+plan(multisession, earlySignal=TRUE)
+f <- future({ stop("bang!") })
+print(f)
+r <- try(resolved(f), silent=TRUE)
+stopifnot(inherits(r, "try-error") || inherits(f, "UniprocessFuture"))
+v <- try(value(f), silent=TRUE)
+stopifnot(inherits(v, "try-error"))
+
+
+message("*** Early signaling of conditions with multisession futures ... DONE")
+
+
+message("*** Early signaling of conditions with multiprocess futures ...")
+
+plan(multiprocess)
+f <- future({ stop("bang!") })
+r <- resolved(f)
+stopifnot(r)
+v <- try(value(f), silent=TRUE)
+stopifnot(inherits(v, "try-error"))
+
+plan(multiprocess, earlySignal=TRUE)
+f <- future({ stop("bang!") })
+print(f)
+r <- try(resolved(f), silent=TRUE)
+stopifnot(inherits(r, "try-error") || inherits(f, "UniprocessFuture"))
+v <- try(value(f), silent=TRUE)
+stopifnot(inherits(v, "try-error"))
+
+message("*** Early signaling of conditions with multiprocess futures ... DONE")
+
+message("*** Early signaling of conditions ... DONE")
+
+source("incl/end.R")
diff --git a/tests/flapply.R b/tests/flapply.R
new file mode 100644
index 0000000..d1313fa
--- /dev/null
+++ b/tests/flapply.R
@@ -0,0 +1,93 @@
+source("incl/start.R")
+library("listenv")
+
+message("*** flapply() ...")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  message("- flapply(x, FUN=vector, ...) ...")
+
+  x <- list(a="integer", b="numeric", c="character", c="list")
+  str(list(x=x))
+
+  y0 <- lapply(x, FUN=vector, length=2L)
+  str(list(y0=y0))
+
+  for (strategy in supportedStrategies()) {
+    message(sprintf("- plan('%s') ...", strategy))
+    plan(strategy)
+    y <- flapply(x, FUN=vector, length=2L)
+    str(list(y=y))
+    stopifnot(identical(y, y0))
+  }
+
+
+  message("- flapply(x, FUN=base::vector, ...) ...")
+
+  x <- list(a="integer", b="numeric", c="character", c="list")
+  str(list(x=x))
+
+  y0 <- lapply(x, FUN=base::vector, length=2L)
+  str(list(y0=y0))
+
+  for (strategy in supportedStrategies()) {
+    message(sprintf("- plan('%s') ...", strategy))
+    plan(strategy)
+    y <- flapply(x, FUN=base::vector, length=2L)
+    str(list(y=y))
+    stopifnot(identical(y, y0))
+  }
+
+
+  message("- flapply(x, FUN=future:::hpaste, ...) ...")
+
+  x <- list(a=c("hello", b=1:100))
+  str(list(x=x))
+
+  y0 <- lapply(x, FUN=future:::hpaste, collapse="; ", maxHead=3L)
+  str(list(y0=y0))
+
+  for (strategy in supportedStrategies()) {
+    message(sprintf("- plan('%s') ...", strategy))
+    plan(strategy)
+    y <- flapply(x, FUN=future:::hpaste, collapse="; ", maxHead=3L)
+    str(list(y=y))
+    stopifnot(identical(y, y0))
+  }
+
+
+  message("- flapply(x, FUN=listenv::listenv, ...) ...")
+
+  x <- list()
+
+  y <- listenv()
+  y$A <- 3L
+  x$a <- y
+
+  y <- listenv()
+  y$A <- 3L
+  y$B <- c("hello", b=1:100)
+  x$b <- y
+
+  print(x)
+
+  y0 <- lapply(x, FUN=listenv::map)
+  str(list(y0=y0))
+
+  for (strategy in supportedStrategies()) {
+    message(sprintf("- plan('%s') ...", strategy))
+    plan(strategy)
+    y <- flapply(x, FUN=listenv::map)
+    str(list(y=y))
+    stopifnot(identical(y, y0))
+  }
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** flapply() ... DONE")
+
+source("incl/end.R")
+
diff --git a/tests/future.R b/tests/future.R
new file mode 100644
index 0000000..6f4e87b
--- /dev/null
+++ b/tests/future.R
@@ -0,0 +1,73 @@
+source("incl/start.R")
+plan(lazy)
+
+message("*** future() ...")
+
+f <- future({
+  42L
+})
+
+print(resolved(f))
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+message("*** future() w/ gc=TRUE ...")
+
+f <- future(42L, gc=TRUE)
+print(f)
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+message("*** future() w/ gc=TRUE ... DONE")
+
+message("*** future() ... DONE")
+
+
+
+plan(lazy)
+
+message("*** future() ...")
+
+f <- future({
+  42L
+})
+
+print(resolved(f))
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+message("*** future() w/ gc=TRUE ...")
+
+f <- future(42L, gc=TRUE)
+print(f)
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+message("*** future() w/ gc=TRUE ... DONE")
+
+
+message("*** future() - exceptions ...")
+
+res <- try(future(42L, evaluator=TRUE))
+stopifnot(inherits(res, "try-error"))
+
+res <- try(future(42L, evaluator=function(...) TRUE))
+stopifnot(inherits(res, "try-error"))
+
+target <- list(name="<unknown>", envir=new.env(), code="Yo!", exists=TRUE)
+res <- try(get_future(target, mustExist=TRUE))
+stopifnot(inherits(res, "try-error"))
+
+message("*** future() - exceptions ... DONE")
+
+
+message("*** future() ... DONE")
+
+source("incl/end.R")
+
diff --git a/tests/futureAssign.R b/tests/futureAssign.R
new file mode 100644
index 0000000..2f30387
--- /dev/null
+++ b/tests/futureAssign.R
@@ -0,0 +1,43 @@
+source("incl/start.R")
+
+message("*** futureAssign() ...")
+plan(lazy)
+
+delayedAssign("a", {
+  cat("Delayed assignment evaluated\n")
+  1
+})
+
+futureAssign("b", {
+  cat("Future assignment evaluated\n")
+  2
+})
+
+## Because "lazy future" is used, the expression/value
+## for 'b' will be resolved at the point.  For other
+## types of futures, it may already have been resolved
+cat(sprintf("b=%s\n", b))
+
+## The expression/value of 'a' is resolved at this point,
+## because a delayed assignment (promise) was used.
+cat(sprintf("a=%s\n", a))
+
+stopifnot(identical(a, 1))
+stopifnot(identical(b, 2))
+
+
+## Potential task name clashes
+u <- new.env()
+v <- new.env()
+futureAssign("a", { 2 }, assign.env=u)
+futureAssign("a", { 4 }, assign.env=v)
+
+cat(sprintf("u$a=%s\n", u$a))
+cat(sprintf("v$a=%s\n", v$a))
+
+stopifnot(identical(u$a, 2))
+stopifnot(identical(v$a, 4))
+
+message("*** futureAssign() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/futureAssign_OP.R b/tests/futureAssign_OP.R
new file mode 100644
index 0000000..2208740
--- /dev/null
+++ b/tests/futureAssign_OP.R
@@ -0,0 +1,116 @@
+source("incl/start.R")
+
+message("*** %<-% ...")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  for (strategy in supportedStrategies()) {
+    message(sprintf("*** %%<-%% with %s futures ...", sQuote(strategy)))
+    plan(strategy)
+
+    rm(list=intersect(c("x", "y"), ls()))
+
+    message("** Future evaluation without globals")
+    v1 %<-% { x <- 1 }
+    stopifnot(!exists("x", inherits=FALSE), identical(v1, 1))
+
+    message("** Future evaluation with globals")
+    a <- 2
+    v2 %<-% { x <- a }
+    stopifnot(!exists("x", inherits=FALSE), identical(v2, a))
+
+    message("** Future evaluation with errors")
+    v3 %<-% {
+      x <- 3
+      stop("Woops!")
+      x
+    }
+    stopifnot(!exists("x", inherits=FALSE))
+    res <- try(identical(v3, 3), silent=TRUE)
+    stopifnot(inherits(res, "try-error"))
+
+
+    y <- listenv::listenv()
+    for (ii in 1:5) {
+      y[[ii]] %<-% {
+        if (ii %% 2 == 0) stop("Woops!")
+        ii
+      }
+    }
+    res <- try(as.list(y), silent=TRUE)
+    stopifnot(inherits(res, "try-error"))
+    z <- y[c(1,3,5)]
+    z <- unlist(z)
+    stopifnot(all(z == c(1,3,5)))
+    res <- try(y[[2]], silent=TRUE)
+    stopifnot(inherits(res, "try-error"))
+    res <- try(y[[4]], silent=TRUE)
+    stopifnot(inherits(res, "try-error"))
+    res <- try(y[c(2,4)], silent=TRUE)
+    stopifnot(inherits(res, "try-error"))
+    res <- try(y[1:2], silent=TRUE)
+    stopifnot(inherits(res, "try-error"))
+
+
+    message("** Future evaluation with progress bar")
+    v4 %<-% {
+      cat("Processing: ")
+      for (ii in 1:10) { cat("."); Sys.sleep(0.1) }
+      cat(" [100%]\n")
+      4
+    }
+
+
+    message("** Collecting results")
+    printf("v1=%s\n", v1)
+    stopifnot(v1 == 1)
+
+    printf("v2=%s\n", v2)
+    stopifnot(v2 == a)
+
+    stopifnot(tryCatch({
+      printf("v3=%s\n", v3)
+    }, error = function(ex) {
+      printf("v3: <%s> (as expect)\n", class(ex)[1])
+      TRUE
+    }))
+
+    printf("v4=%s\n", v4)
+    #stopifnot(v4 == 4)
+
+
+    message("** Left-to-right and right-to-left future assignments")
+    c %<-% 1
+    printf("c=%s\n", c)
+    1 %=>% d
+    printf("d=%s\n", d)
+    stopifnot(d == c)
+
+
+
+    message("** Nested future assignments")
+    a %<-% {
+      b <- 1
+      c %<-% 2
+      3 -> d
+      4 %=>% e
+      b + c + d + e
+    }
+    printf("a=%s\n", a)
+    stopifnot(a == 10)
+
+    { a + 1 } %=>% b
+    printf("b=%s\n", b)
+    stopifnot(b == a + 1)
+
+    message(sprintf("*** %%<-%% with %s futures ... DONE", sQuote(strategy)))
+  } # for (strategy in ...)
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** %<-% ... DONE")
+
+source("incl/end.R")
diff --git a/tests/futureAssign_OP_with_environment.R b/tests/futureAssign_OP_with_environment.R
new file mode 100644
index 0000000..403f882
--- /dev/null
+++ b/tests/futureAssign_OP_with_environment.R
@@ -0,0 +1,54 @@
+source("incl/start.R")
+plan(lazy)
+
+## BACKWARD COMPATIBILITY
+if (getRversion() < "3.2.0") {
+  names <- function(x) if (is.environment(x)) ls(envir=x) else base::names(x)
+}
+
+message("*** %<-% to environment ...")
+
+## - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+## Async delayed assignment (infix operator)
+## - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+z <- new.env()
+stopifnot(length(names(z)) == 0L)
+
+message("*** %<-% to environment: Assign by index (not allowed)")
+res <- try(z[[1]] %<-% { 2 }, silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** %<-% to environment: Assign by name (new)")
+z$B %<-% TRUE
+stopifnot(length(z) == 2) # sic!
+stopifnot("B" %in% ls(z))
+
+y <- as.list(z)
+str(y)
+stopifnot(length(y) == 1)
+stopifnot(identical(names(y), "B"))
+
+
+message("*** %<-% to environment: Potential task name clashes")
+u <- new.env()
+u$a %<-% 1
+stopifnot(length(u) == 2)
+stopifnot("a" %in% names(u))
+fu <- futureOf(u$a)
+
+v <- new.env()
+v$a %<-% 2
+stopifnot(length(v) == 2)
+stopifnot("a" %in% names(v))
+fv <- futureOf(v$a)
+stopifnot(!identical(fu, fv))
+
+fu <- futureOf(u$a)
+stopifnot(!identical(fu, fv))
+
+stopifnot(identical(u$a, 1))
+stopifnot(identical(v$a, 2))
+
+message("*** %<-% to environment ... DONE")
+
+source("incl/end.R")
diff --git a/tests/futureAssign_OP_with_listenv.R b/tests/futureAssign_OP_with_listenv.R
new file mode 100644
index 0000000..deab2a5
--- /dev/null
+++ b/tests/futureAssign_OP_with_listenv.R
@@ -0,0 +1,86 @@
+source("incl/start.R")
+library("listenv")
+plan(lazy)
+
+message("*** %<-% to listenv ...")
+
+## - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+## Future assignment via infix operator
+## - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+z <- listenv()
+stopifnot(length(names(z)) == 0)
+
+message("*** %<-% to listenv: Assign by index")
+z[[1]] %<-% { 2 }
+stopifnot(length(z) == 1)
+stopifnot(length(names(z)) == 0)
+
+z[[1]] %<-% { 2 }
+stopifnot(length(z) == 1)
+stopifnot(length(names(z)) == 0)
+
+z[[4]] %<-% { "async!" }
+stopifnot(length(z) == 4)
+stopifnot(length(names(z)) == 0)
+
+message("*** %<-% to listenv: Update names")
+names(z) <- c("A", "B", "C", "D")
+stopifnot(identical(names(z), c("A", "B", "C", "D")))
+
+
+message("*** %<-% to listenv: Assign by name (existing)")
+z$B %<-% TRUE
+stopifnot(length(z) == 4)
+stopifnot(identical(names(z), c("A", "B", "C", "D")))
+
+y <- as.list(z)
+str(y)
+stopifnot(length(y) == 4)
+stopifnot(identical(names(y), c("A", "B", "C", "D")))
+
+
+message("*** %<-% to listenv: Asserting no name clashes among futures")
+u <- listenv()
+u$a %<-% 1
+stopifnot(identical(names(u), "a"))
+fu <- futureOf(u$a)
+
+v <- listenv()
+v$a %<-% 2
+stopifnot(identical(names(v), "a"))
+fv <- futureOf(v$a)
+stopifnot(!identical(fu, fv))
+
+fu <- futureOf(u$a)
+stopifnot(!identical(fu, fv))
+
+stopifnot(identical(u$a, 1))
+stopifnot(identical(v$a, 2))
+
+
+message("*** %<-% to listenv: multiple dimensions ...")
+
+x0 <- list()
+length(x0) <- 6
+dim(x0) <- c(3,2)
+
+x <- listenv()
+length(x) <- 6
+dim(x) <- c(3,2)
+
+for (cc in 1:ncol(x)) {
+  for (rr in 1:nrow(x)) {
+    x0[[rr,cc]] <- sprintf("(%s,%s)", rr, cc)
+    x[[rr,cc]] %<-% sprintf("(%s,%s)", rr, cc)
+  }
+}
+
+y <- as.list(x)
+dim(y) <- dim(x)
+stopifnot(identical(y, x0))
+
+message("*** %<-% to listenv: multiple dimensions ... DONE")
+
+message("*** %<-% to listenv ... DONE")
+
+source("incl/end.R")
diff --git a/tests/futureCall.R b/tests/futureCall.R
new file mode 100644
index 0000000..fcb5dd0
--- /dev/null
+++ b/tests/futureCall.R
@@ -0,0 +1,28 @@
+source("incl/start.R")
+
+message("*** futureCall() ...")
+plan(lazy)
+
+f1 <- future(do.call(rnorm, args=list(n=100)))
+f2 <- futureCall(rnorm, args=list(n=100))
+
+set.seed(42L)
+v0 <- rnorm(n=100)
+str(list(v0=v0))
+
+set.seed(42L)
+v1 <- value(f1)
+str(list(v1=v1))
+
+set.seed(42L)
+v2 <- value(f2)
+str(list(v2=v2))
+
+## Because we use lazy futures and set the
+## random seed just before they are resolved
+stopifnot(all.equal(v1, v0))
+stopifnot(all.equal(v1, v2))
+
+message("*** futureCall() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/futureOf.R b/tests/futureOf.R
new file mode 100644
index 0000000..8a14688
--- /dev/null
+++ b/tests/futureOf.R
@@ -0,0 +1,25 @@
+source("incl/start.R")
+library("listenv")
+plan(lazy)
+
+message("*** futureOf() ...")
+
+a %<-% { 1 }
+
+f1 <- futureOf("a")
+print(f1)
+f2 <- futureOf(a)
+print(f2)
+stopifnot(identical(f2, f1))
+
+fs <- futureOf()
+print(fs)
+
+## Non-existing object
+res <- try(futureOf("non-exiting-object", mustExist=TRUE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** futureOf() ... DONE")
+
+source("incl/end.R")
+
diff --git a/tests/futureOf_with_environment.R b/tests/futureOf_with_environment.R
new file mode 100644
index 0000000..6feb406
--- /dev/null
+++ b/tests/futureOf_with_environment.R
@@ -0,0 +1,81 @@
+source("incl/start.R")
+
+suppressWarnings(rm(list=c("x", "z")))
+
+message("*** futureOf() with environment ...")
+
+message("*** futureOf() with environment - future assignments ...")
+
+x <- new.env()
+x$a %<-% { 1 }
+
+f1 <- futureOf("a", envir=x)
+print(f1)
+f2 <- futureOf(a, envir=x)
+f3 <- futureOf(x[["a"]])
+f4 <- futureOf(x$a)
+stopifnot(identical(f2, f1), identical(f3, f1), identical(f4, f1))
+
+## Identify all futures
+fs <- futureOf(envir=x)
+print(fs)
+stopifnot(identical(names(fs), c("a")))
+stopifnot(identical(fs$a, f1))
+
+fsD <- futureOf(envir=x, drop=TRUE)
+print(fsD)
+stopifnot(all(sapply(fsD, FUN=inherits, "Future")))
+stopifnot(identical(fsD, fs))
+
+message("*** futureOf() with environment - future assignments ... DONE")
+
+
+message("*** futureOf() with environment - futures ...")
+
+x <- new.env()
+x$a <- future({ 1 })
+
+f1 <- futureOf("a", envir=x)
+print(f1)
+stopifnot(identical(f1, x$a))
+f2 <- futureOf(a, envir=x)
+stopifnot(identical(f2, x$a))
+f3 <- futureOf(x[["a"]])
+stopifnot(identical(f3, x$a))
+f4 <- futureOf(x$a)
+stopifnot(identical(f4, x$a))
+
+## Identify all futures
+fs <- futureOf(envir=x)
+print(fs)
+stopifnot(identical(names(fs), c("a")))
+stopifnot(identical(fs$a, f1))
+
+fsD <- futureOf(envir=x, drop=TRUE)
+print(fsD)
+stopifnot(all(sapply(fsD, FUN=inherits, "Future")))
+stopifnot(identical(fsD, fs))
+
+message("*** futureOf() with environment - futures ... DONE")
+
+
+message("*** futureOf() with environment - exceptions ...")
+
+## Invalid subset
+res <- try(futureOf(x[[0]], mustExist=FALSE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+res <- try(futureOf(x[[0]], mustExist=TRUE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+res <- try(futureOf(x[[10]], mustExist=TRUE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+res <- try(futureOf(x[[1+2i]], mustExist=TRUE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** futureOf() with environment - exceptions ... DONE")
+
+message("*** futureOf() with environment ... DONE")
+
+source("incl/end.R")
diff --git a/tests/futureOf_with_listenv.R b/tests/futureOf_with_listenv.R
new file mode 100644
index 0000000..7ae6736
--- /dev/null
+++ b/tests/futureOf_with_listenv.R
@@ -0,0 +1,108 @@
+source("incl/start.R")
+library("listenv")
+plan(lazy)
+
+message("*** futureOf() with listenv ...")
+
+message("*** futureOf() with listenv - future assignments ...")
+
+x <- listenv()
+x$a %<-% { 1 }
+
+f1 <- futureOf("a", envir=x)
+print(f1)
+f2 <- futureOf(a, envir=x)
+f3 <- futureOf(1, envir=x)
+f4 <- futureOf(x[["a"]])
+f5 <- futureOf(x$a)
+f6 <- futureOf(x[[1]])
+stopifnot(identical(f2, f1), identical(f3, f2), identical(f4, f3),
+          identical(f5, f4), identical(f6, f5))
+
+x[[3]] %<-% { 3 }
+x$d %<-% { 4 }
+x[[5]] <- 5
+
+## Identify all futures
+fs <- futureOf(envir=x)
+print(fs)
+stopifnot(identical(names(fs), names(x)))
+stopifnot(identical(fs$a, f1))
+stopifnot(identical(fs[[3]], futureOf(3L, envir=x)))
+stopifnot(identical(fs$d, futureOf("d", envir=x)))
+
+fsD <- futureOf(envir=x, drop=TRUE)
+print(fsD)
+stopifnot(all(sapply(fsD, FUN=inherits, "Future")))
+stopifnot(!identical(fsD, fs))
+
+message("*** futureOf() with listenv - future assignments ... DONE")
+
+
+message("*** futureOf() with listenv - futures ...")
+
+x <- listenv()
+x$a <- future({ 1 })
+
+f1 <- futureOf("a", envir=x)
+print(f1)
+stopifnot(identical(f1, x$a))
+f2 <- futureOf(a, envir=x)
+stopifnot(identical(f2, x$a))
+f3 <- futureOf(1, envir=x)
+stopifnot(identical(f3, x$a))
+f4 <- futureOf(x[["a"]])
+stopifnot(identical(f4, x$a))
+f5 <- futureOf(x$a)
+stopifnot(identical(f5, x$a))
+f6 <- futureOf(x[[1]])
+stopifnot(identical(f6, x$a))
+
+x[[3]] <- future({ 3 })
+x$d <- future({ 4 })
+x[[5]] <- 5
+
+## Identify all futures
+fs <- futureOf(envir=x)
+print(fs)
+stopifnot(identical(names(fs), names(x)))
+stopifnot(identical(fs$a, f1))
+stopifnot(identical(fs[[3]], futureOf(3L, envir=x)))
+stopifnot(identical(fs$d, futureOf("d", envir=x)))
+
+fsD <- futureOf(envir=x, drop=TRUE)
+print(fsD)
+stopifnot(all(sapply(fsD, FUN=inherits, "Future")))
+stopifnot(!identical(fsD, fs))
+
+message("*** futureOf() with listenv - futures ... DONE")
+
+
+message("*** futureOf() with listenv - exceptions ...")
+
+## Invalid subset
+res <- try(futureOf(x[[0]], mustExist=FALSE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+res <- try(futureOf(x[[0]], mustExist=TRUE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+## Out-of-bound subscript, cf lists
+stopifnot(is.na(futureOf(x[[10]], mustExist=FALSE)))
+res <- try(futureOf(x[[10]], mustExist=TRUE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+## Invalid subscript
+res <- try(futureOf(x[[1+2i]], mustExist=TRUE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+## Non-existing object
+res <- try(futureOf(z[[1]], mustExist=TRUE), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** futureOf() with listenv - exceptions ... DONE")
+
+
+message("*** futureOf() with listenv ... DONE")
+
+source("incl/end.R")
diff --git a/tests/futures.R b/tests/futures.R
new file mode 100644
index 0000000..9753102
--- /dev/null
+++ b/tests/futures.R
@@ -0,0 +1,101 @@
+source("incl/start.R")
+library("listenv")
+
+## Backward compatibility
+if (getRversion() < "3.2.0") {
+  names <- function(x) {
+    if (class(x)[1] == "environment") {
+      ls(envir=x, all.names=TRUE)
+    } else {
+      base::names(x)
+    }
+  }
+}
+
+dims <- list(
+  NULL,
+  c(1,6),
+  c(2,3),
+  c(2,3,1),
+  c(2,1,3,1)
+)
+
+
+message("*** futures() / resolved() / values() ...")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  for (type in c("list", "environment", "listenv")) {
+    message(sprintf("Type of object: %s", type))
+
+    for (strategy in supportedStrategies()) {
+      message("Type of future: ", strategy)
+      plan(strategy)
+
+      for (dim in dims) {
+        message("Dimensions: ", deparse(dim))
+
+        if (type == "list") {
+          x <- list()
+        } else if (type == "listenv") {
+          x <- listenv()
+        } else if (type == "environment") {
+          x <- new.env()
+        }
+
+        x$a <- 1
+        x$b <- future(2)
+        x$c <- 3
+        if (type != "list") x$d %<-% { 4 }
+        if (type != "environment") x[[6]] <- 6
+        str(x)
+
+        if (!is.null(dim)) {
+          if (type != "environment") {
+            names <- names(x)
+            dim(x) <- dim
+            dimnames(x) <- lapply(dim, FUN=function(n) letters[1:n])
+            names(x) <- names
+          }
+        }
+
+        f <- futures(x)
+        str(f)
+        if (type != "environment") {
+          stopifnot(length(f) == length(x))
+          stopifnot(identical(names(f), names(x)))
+        }
+        stopifnot(identical(dim(f), dim(x)))
+        stopifnot(identical(dimnames(f), dimnames(x)))
+
+        r <- resolved(x)
+        str(r)
+        if (type != "environment") {
+          stopifnot(length(r) == length(x))
+          stopifnot(identical(names(r), names(x)))
+        }
+        stopifnot(identical(dim(r), dim(x)))
+        stopifnot(identical(dimnames(r), dimnames(x)))
+
+        v <- values(x)
+        str(v)
+        if (type != "environment") {
+          stopifnot(length(v) == length(x))
+          stopifnot(identical(names(v), names(x)))
+        }
+        stopifnot(identical(dim(v), dim(x)))
+        stopifnot(identical(dimnames(v), dimnames(x)))
+      } # for (dim ...)
+    } # for (strategy ...)
+
+    message(sprintf("*** futures() - %s ... DONE", type))
+  } # for (type ...)
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** futures() / resolved() / values() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/globals,NSE.R b/tests/globals,NSE.R
new file mode 100644
index 0000000..6ca3e16
--- /dev/null
+++ b/tests/globals,NSE.R
@@ -0,0 +1,47 @@
+source("incl/start.R")
+library("listenv")
+
+message("*** Globals w/ non-standard evaluation (NSE) ...")
+
+data <- data.frame(x=1:5, y=1:5)
+v0 <- subset(data, x < 3)$y
+
+for (strategy in supportedStrategies()) {
+  message(sprintf("- Strategy: %s ...", strategy))
+  
+  plan(strategy)
+
+  ## Assert option is passed on to future
+  options(future.globals.onMissing="error")
+  opt1 %<-% getOption("future.globals.onMissing")
+  stopifnot(identical(opt1, "error"))
+
+  options(future.globals.onMissing="ignore")
+  opt2 %<-% getOption("future.globals.onMissing")
+  stopifnot(identical(opt2, "ignore"))
+
+  options(future.globals.onMissing="error")
+  res <- try({ v1 %<-% subset(data, x < 3)$y }, silent=TRUE)
+  stopifnot(inherits(res, "try-error"))
+
+  options(future.globals.onMissing="ignore")
+  v2 %<-% subset(data, x < 3)$y
+  stopifnot(identical(v2, v0))
+
+  ## Nested futures (requires option is passed on to future)
+  plan(list(lazy, strategy))
+  options(future.globals.onMissing="ignore")
+  v3 %<-% {
+    a %<-% subset(data, x < 3)$y
+    a
+  }
+  stopifnot(identical(v3, v0))
+
+  message(sprintf("- Strategy: %s ... DONE", strategy))
+}
+
+
+message("*** Globals w/ non-standard evaluation (NSE) ... DONE")
+
+source("incl/end.R")
+
diff --git a/tests/globals,resolve.R b/tests/globals,resolve.R
new file mode 100644
index 0000000..12238ef
--- /dev/null
+++ b/tests/globals,resolve.R
@@ -0,0 +1,47 @@
+source("incl/start.R")
+library("listenv")
+
+oopts <- c(oopts, options(future.globals.resolve=TRUE))
+setTimeLimit(cpu=10, elapsed=10, transient=TRUE)
+
+message("*** Tricky use cases related to globals (part 2) ...")
+
+## Allow for two (sic!) background processes
+plan(multisession, workers=3L)
+
+env <- new.env()
+
+## Create future #1 (consumes background process #1)
+env$a %<-% { 5 }
+
+## Create future #2 (consumes background process #2)
+b %<-% { "a" }
+
+## Resolve future #2 (frees up background process #2)
+message(sprintf("b=%s\n", sQuote(b)))
+
+## Create future #3 (consumes background process #2)
+## THIS IS THE TRICKY PART:
+## Two globals are identified `env` and `b` and both are resolved.
+## However, object `env[[b]]` (here element `a` of environment `env`)
+## is not touched and therefore not resolved (since it is a future)
+## unless environment `env` is resolved recursively. (Issue #49)
+y %<-% { env[[b]] }
+
+## Resolve future #3
+message(sprintf("y=%s\n", y))
+
+## Resolve future #1 if not already done
+str(as.list(env))
+
+## Create future #4
+## Since future #1 is resolved it will work at this point
+y %<-% { env[[b]] }
+## Resolve future #4
+message(sprintf("y=%s\n", y))
+
+message("*** Tricky use cases related to globals (part 2) ... DONE")
+
+## Cleanup
+setTimeLimit()
+source("incl/end.R")
diff --git a/tests/globals,toolarge.R b/tests/globals,toolarge.R
new file mode 100644
index 0000000..63ba473
--- /dev/null
+++ b/tests/globals,toolarge.R
@@ -0,0 +1,39 @@
+source("incl/start.R")
+library("listenv")
+
+message("*** Globals - too large ...")
+
+ooptsT <- options(future.globals.maxSize=1024L)
+limit <- getOption("future.globals.maxSize")
+cat(sprintf("Max total size of globals: %g bytes\n", limit))
+
+plan(multisession)
+
+exprs <- list(
+  A = substitute({ a }, env=list()),
+  B = substitute({ a*b }, env=list()),
+  C = substitute({ a*b*c }, env=list()),
+  D = substitute({ a*b*c*d }, env=list()),
+  E = substitute({ a*b*c*d*e }, env=list())
+)
+
+a <- 1:1000
+b <- 1:900
+c <- 1:800
+d <- 1:700
+e <- 1
+
+for (name in names(exprs)) {
+  message(sprintf("Expression %s:", name))
+  expr <- exprs[[name]]
+  print(expr)
+  res <- tryCatch({
+    f <- future(expr, substitute=FALSE)
+  }, error = function(ex) ex)
+  print(res)
+  stopifnot(inherits(res, "error"))
+}
+
+message("*** Globals - too large ... DONE")
+
+source("incl/end.R")
diff --git a/tests/globals,tricky.R b/tests/globals,tricky.R
new file mode 100644
index 0000000..df39a88
--- /dev/null
+++ b/tests/globals,tricky.R
@@ -0,0 +1,96 @@
+source("incl/start.R")
+library("listenv")
+oopts <- c(oopts, options(
+  future.globals.resolve=TRUE,
+  future.globals.onMissing="error"
+))
+
+message("*** Tricky use cases related to globals ...")
+
+strategies <- supportedStrategies()
+strategies <- setdiff(strategies, "multiprocess")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  message("availableCores(): ", availableCores())
+
+  message("- Local variables with the same name as globals ...")
+
+  methods <- c("conservative", "ordered")
+
+  for (method in methods) {
+    options(future.globals.method=method)
+    message(sprintf("Method for identifying globals: '%s' ...", method))
+
+    for (strategy in strategies) {
+      message(sprintf("- plan('%s') ...", strategy))
+      plan(strategy)
+
+      a <- 3
+
+      yTruth <- local({
+        b <- a
+        a <- 2
+        a*b
+      })
+
+      y %<-% {
+        b <- a
+        a <- 2
+        a*b
+      }
+
+      rm(list="a")
+
+      res <- try(y, silent=TRUE)
+      if (method == "conservative" && strategy %in% c("lazy", "multisession")) {
+        str(list(res=res))
+        stopifnot(inherits(res, "try-error"))
+      } else {
+        message(sprintf("y=%g", y))
+        stopifnot(identical(y, yTruth))
+      }
+
+
+      res <- listenv()
+      a <- 1
+      for (ii in 1:3) {
+        res[[ii]] %<-% {
+          b <- a*ii
+          a <- 0
+          b
+        }
+      }
+      rm(list="a")
+
+      res <- try(unlist(res), silent=TRUE)
+      if (method == "conservative" && strategy %in% c("lazy", "multisession")) {
+        str(list(res=res))
+        stopifnot(inherits(res, "try-error"))
+      } else {
+        print(res)
+        stopifnot(all(res == 1:3))
+      }
+
+
+      ## Assert that `a` is resolved and turned into a constant future
+      ## at the moment when future `b` is created.
+      ## Requires options(future.globals.resolve=TRUE).
+      a <- future(1)
+      b <- future(value(a)+1)
+      rm(list="a")
+      message(sprintf("value(b)=%g", value(b)))
+      stopifnot(value(b) == 2)
+    } ## for (strategy ...)
+
+    message(sprintf("Method for identifying globals: '%s' ... DONE", method))
+  }
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** Tricky use cases related to globals ... DONE")
+
+source("incl/end.R")
diff --git a/tests/globalsOf,tweaks.R b/tests/globalsOf,tweaks.R
new file mode 100644
index 0000000..9a236b9
--- /dev/null
+++ b/tests/globalsOf,tweaks.R
@@ -0,0 +1,44 @@
+source("incl/start.R")
+library("globals")
+
+
+message("*** tweakExpression() ...")
+
+expr <- substitute({ a <<- 1; b <- 2; 3 ->> c }, env=list())
+print(expr)
+exprT <- tweakExpression(expr)
+print(exprT)
+
+
+b <- 2
+exprs <- list(
+  A = substitute({ a <- b; }, env=list()),
+  B = substitute({ a <- b; b <- 1 }, env=list()),
+  C = substitute({ a <- 1; a <- 2 }, env=list()),
+  D = substitute({ a <<- 1; a <- 2 }, env=list()),
+  E = substitute({ a <<- 1 }, env=list())
+)
+
+truth <- list(
+  A = "b",
+  B = "b",
+  C = character(0L),
+  D = character(0L),
+  E = character(0L)
+)
+
+
+for (kk in seq_along(exprs)) {
+  name <- names(exprs)[kk]
+  expr <- exprs[[kk]]
+  cat(sprintf("Expression #%d ('%s'):", kk, name))
+  print(expr)
+  globals <- globalsOf(expr, tweak=tweakExpression)
+  globals <- cleanup(globals)
+  str(globals)
+  stopifnot(identical(names(globals), truth[[name]]))
+}
+
+message("*** tweakExpression() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/incl/end.R b/tests/incl/end.R
new file mode 100644
index 0000000..1441991
--- /dev/null
+++ b/tests/incl/end.R
@@ -0,0 +1,34 @@
+## Undo future strategy
+future::plan(oplan)
+
+
+## Undo options
+## (a) Added
+added <- setdiff(names(options()), names(oopts0))
+opts <- vector("list", length=length(added))
+names(opts) <- added
+options(opts)
+## (b) Modified
+options(oopts)
+## (c) Assert that everything was undone
+stopifnot(identical(options(), oopts0))
+
+
+## Undo system environment variables
+## (a) Added
+cenvs <- Sys.getenv()
+added <- setdiff(names(cenvs), names(oenvs))
+for (name in added) Sys.unsetenv(name)
+## (b) Modified?
+for (name in intersect(names(cenvs), names(oenvs))) {
+  if (!identical(cenvs[[name]], oenvs[[name]])) {
+    Sys.setenv(name, oenvs[[name]])
+  }
+}
+## (c) Assert that everything was undone
+stopifnot(identical(Sys.getenv(), oenvs))
+
+
+## Undo variables
+rm(list=c(setdiff(ls(), ovars)))
+
diff --git a/tests/incl/start,load-only.R b/tests/incl/start,load-only.R
new file mode 100644
index 0000000..8bf631c
--- /dev/null
+++ b/tests/incl/start,load-only.R
@@ -0,0 +1,43 @@
+## Record original state
+ovars <- ls()
+oenvs <- oenvs0 <- Sys.getenv()
+oopts0 <- options()
+oopts <- options(
+  warn=1L,
+  mc.cores=2L,
+  future.debug=TRUE
+)
+oplan <- future::plan()
+
+## Use eager futures by default
+future::plan("eager")
+
+## Private future functions
+.onLoad <- future:::.onLoad
+.onAttach <- future:::.onAttach
+asIEC <- future:::asIEC
+ClusterRegistry <- future:::ClusterRegistry
+constant <- future:::constant
+detectCores <- future:::detectCores
+flapply <- future:::flapply
+FutureRegistry <- future:::FutureRegistry
+gassign <- future:::gassign
+get_future <- future:::get_future
+geval <- future:::geval
+grmall <- future:::grmall
+hpaste <- future:::hpaste
+importParallel <- future:::importParallel
+mdebug <- future:::mdebug
+myExternalIP <- future:::myExternalIP
+myInternalIP <- future:::myInternalIP
+parseCmdArgs <- future:::parseCmdArgs
+requestCore <- future:::requestCore
+requestNode <- future:::requestNode
+requirePackages <- future:::requirePackages
+supportedStrategies <- future:::supportedStrategies
+tweakExpression <- future:::tweakExpression
+whichIndex <- future:::whichIndex
+
+## Local functions for test scripts
+printf <- function(...) cat(sprintf(...))
+mstr <- function(...) message(paste(capture.output(str(...)), collapse="\n"))
diff --git a/tests/incl/start.R b/tests/incl/start.R
new file mode 100644
index 0000000..34cfe1c
--- /dev/null
+++ b/tests/incl/start.R
@@ -0,0 +1,2 @@
+library("future")
+source("incl/start,load-only.R")
diff --git a/tests/invalid-owner.R b/tests/invalid-owner.R
new file mode 100644
index 0000000..cb3a922
--- /dev/null
+++ b/tests/invalid-owner.R
@@ -0,0 +1,92 @@
+source("incl/start.R")
+
+## Local functions
+usedNodes <- function(future) {
+  ## Number of unresolved cluster futures
+  workers <- future$workers
+  reg <- sprintf("workers-%s", attr(workers, "name"))
+  c(used=length(future:::FutureRegistry(reg, action="list")), total=length(workers))
+}
+
+## This test requires at least two background processes
+plan(multisession, workers=3L)
+
+message("*** future() - invalid ownership ...")
+
+## This R process
+uuid <- future:::uuid()
+cat(sprintf("Main R process: %s\n", uuid))
+
+message("- Asserting ownership ...")
+
+message("Creating future #1:")
+f1 <- future({ future:::uuid() })
+stopifnot(inherits(f1, "MultisessionFuture"))
+cat(sprintf("Future #1 session: %d\n", f1$node))
+v1 <- value(f1)
+cat(sprintf("Future #1 R process: %s\n", v1))
+stopifnot(v1 != uuid)
+
+message("Creating future #2:")
+f2 <- future({ future:::uuid() })
+stopifnot(inherits(f2, "MultisessionFuture"))
+cat(sprintf("Future #2 session: %d\n", f2$node))
+v2 <- value(f2)
+cat(sprintf("Future #2 R process: %s\n", v2))
+stopifnot(v2 != uuid)
+
+message("Creating future #3:")
+f3 <- future({ f1$owner })
+stopifnot(inherits(f3, "MultisessionFuture"))
+cat(sprintf("Future #3 session: %d\n", f3$node))
+v3 <- value(f3)
+cat(sprintf("Future #3 owner: %s\n", v3))
+stopifnot(v3 == uuid)
+
+message("Creating future #4:")
+f4 <- future({ f1$owner })
+stopifnot(inherits(f4, "MultisessionFuture"))
+cat(sprintf("Future #4 session: %d\n", f4$node))
+v4 <- value(f4)
+cat(sprintf("Future #4 owner: %s\n", v4))
+stopifnot(v4 == uuid)
+
+message("Creating future #5:")
+f5 <- future({ stopifnot(f1$owner != future:::uuid()); "not-owner" })
+stopifnot(inherits(f5, "MultisessionFuture"))
+v5 <- value(f5)
+stopifnot(v5 == "not-owner")
+
+message("- Asserting ownership ... DONE")
+
+
+message("- Trying with invalid ownership ...")
+
+message("Creating future #1:")
+f1 <- future({ Sys.sleep(5); 42L })
+print(f1)
+cat(sprintf("Future #1 session: %d\n", f1$node))
+stopifnot(identical(f1$owner, uuid))
+print(usedNodes(f1))
+
+message("Creating future #2:")
+f2 <- future({ value(f1) })
+print(f2)
+cat(sprintf("Future #2 session: %d\n", f2$node))
+stopifnot(identical(f2$owner, uuid))
+print(usedNodes(f2))
+
+message("Getting value of future #2:")
+res <- try(value(f2), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+v1 <- value(f1)
+print(v1)
+stopifnot(v1 == 42L)
+
+message("- Trying with invalid ownership ... DONE")
+
+message("*** future() - invalid ownership ... DONE")
+
+source("incl/end.R")
diff --git a/tests/lazy.R b/tests/lazy.R
new file mode 100644
index 0000000..cc7b24e
--- /dev/null
+++ b/tests/lazy.R
@@ -0,0 +1,112 @@
+source("incl/start.R")
+library("listenv")
+plan(lazy)
+
+message("*** lazy() ...")
+
+message("*** lazy() without globals")
+
+f <- lazy({
+  42L
+})
+stopifnot(inherits(f, "LazyFuture"))
+
+## Check whether a lazy future is resolved
+## or not will force evaluation
+print(resolved(f))
+stopifnot(resolved(f))
+
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+message("*** lazy() with globals")
+## A global variable
+a <- 0
+f <- lazy({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+print(f)
+
+## Although 'f' is a _lazy_ future and therefore
+## resolved/evaluates the future expression only
+## when the value is requested, any global variables
+## identified in the expression (here 'a') are
+## "frozen" at the time point when the future is
+## created.  Because of this, 'a' preserved the
+## zero value although we reassign it below
+a <- 7  ## Make sure globals are frozen
+##if ("covr" %in% loadedNamespaces()) v <- 0 else ## WORKAROUND
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+
+
+## A global variable (but without "freezing" it)
+a <- 0
+f <- lazy({
+  b <- 3
+  c <- 2
+  a * b * c
+}, globals=FALSE)
+print(f)
+
+## Since 'a' is a global variable in _lazy_ future 'f',
+## which still hasn't been resolved, any changes to
+## 'a' until 'f' is resolved, will affect its value.
+a <- 7 ## ... but not in this case
+##if ("covr" %in% loadedNamespaces()) v <- 42 else ## WORKAROUND
+v <- value(f)
+print(v)
+stopifnot(v == 42)
+
+
+message("*** lazy() with globals (tricky)")
+x <- listenv()
+for (ii in 1:5) x[[ii]] <- lazy({ ii }, globals=TRUE)
+v <- sapply(x, FUN=value)
+stopifnot(all(v == 1:5))  ## Make sure globals are frozen
+
+x <- listenv()
+for (ii in 1:5) x[[ii]] <- lazy({ ii }, globals=FALSE)
+v <- sapply(x, FUN=value)
+stopifnot(all(v == 5L))  ## Make sure globals are not frozen
+
+
+message("*** lazy() and errors ...")
+f <- lazy({
+  stop("Whoops!")
+  1
+})
+print(f)
+v <- value(f, signal=FALSE)
+print(v)
+stopifnot(inherits(v, "simpleError"))
+
+res <- try({ v <- value(f) }, silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+## Error is repeated
+res <- try(value(f), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+message("*** lazy() and errors ... DONE")
+
+
+message("*** lazy() - exceptions ...")
+
+res <- try(lazy(42L, local=FALSE, globals=TRUE), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+message("*** lazy() - exceptions ... DONE")
+
+
+message("*** lazy() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/mandelbrot.R b/tests/mandelbrot.R
new file mode 100644
index 0000000..c1a9d67
--- /dev/null
+++ b/tests/mandelbrot.R
@@ -0,0 +1,14 @@
+source("incl/start.R")
+
+message("mandelbrot() ...")
+
+counts <- mandelbrot(xmid=-0.75, ymid=0.0, side=3.0, resolution=100L)
+img <- as.raster(counts)
+if (getRversion() >= "3.2.0") {
+  plot(img)
+  plot(counts)
+}
+
+message("mandelbrot() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/multicore.R b/tests/multicore.R
new file mode 100644
index 0000000..6eddc62
--- /dev/null
+++ b/tests/multicore.R
@@ -0,0 +1,106 @@
+source("incl/start.R")
+library("listenv")
+plan(multicore)
+
+message("*** multicore() ...")
+
+for (cores in 1:min(3L, availableCores("multicore"))) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  if (!supportsMulticore()) {
+    message(sprintf("Multicore futures are not supporting on '%s'. Falling back to use synchroneous eager futures", .Platform$OS))
+  }
+
+  for (globals in c(FALSE, TRUE)) {
+
+  message(sprintf("*** multicore(..., globals=%s) without globals", globals))
+
+  f <- multicore({
+    42L
+  }, globals=globals)
+  stopifnot(inherits(f, "MulticoreFuture") || ((cores ==1 || !supportsMulticore()) && inherits(f, "EagerFuture")))
+
+  print(resolved(f))
+  y <- value(f)
+  print(y)
+  stopifnot(y == 42L)
+
+
+  message(sprintf("*** multicore(..., globals=%s) with globals", globals))
+  ## A global variable
+  a <- 0
+  f <- multicore({
+    b <- 3
+    c <- 2
+    a * b * c
+  }, globals=globals)
+  print(f)
+
+
+  ## A multicore future is evaluated in a separated
+  ## forked process.  Changing the value of a global
+  ## variable should not affect the result of the
+  ## future.
+  a <- 7  ## Make sure globals are frozen
+##  if ("covr" %in% loadedNamespaces()) v <- 0 else ## WORKAROUND
+  v <- value(f)
+  print(v)
+  stopifnot(v == 0)
+
+
+  message(sprintf("*** multicore(..., globals=%s) with globals and blocking", globals))
+  x <- listenv()
+  for (ii in 1:4) {
+    message(sprintf(" - Creating multicore future #%d ...", ii))
+    x[[ii]] <- multicore({ ii }, globals=globals)
+  }
+  message(sprintf(" - Resolving %d multicore futures", length(x)))
+##  if ("covr" %in% loadedNamespaces()) v <- 1:4 else ## WORKAROUND
+  v <- sapply(x, FUN=value)
+  stopifnot(all(v == 1:4))
+
+
+  message(sprintf("*** multicore(..., globals=%s) and errors", globals))
+  f <- multicore({
+    stop("Whoops!")
+    1
+  }, globals=globals)
+  print(f)
+  v <- value(f, signal=FALSE)
+  print(v)
+  stopifnot(inherits(v, "simpleError"))
+
+  res <- try(value(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+
+  ## Error is repeated
+  res <- try(value(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+
+  } # for (globals ...)
+
+
+  message("*** multicore(..., workers=1L) ...")
+
+  a <- 2
+  b <- 3
+  yTruth <- a * b
+
+  f <- multicore({ a * b }, workers=1L)
+  rm(list=c("a", "b"))
+
+  v <- value(f)
+  print(v)
+  stopifnot(v == yTruth)
+
+  message("*** multicore(..., workers=1L) ... DONE")
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** multicore() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/multiprocess.R b/tests/multiprocess.R
new file mode 100644
index 0000000..eadc34a
--- /dev/null
+++ b/tests/multiprocess.R
@@ -0,0 +1,133 @@
+source("incl/start.R")
+library("listenv")
+plan(multiprocess)
+
+message("*** multiprocess() ...")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  ## No global variables
+  f <- multiprocess({
+    42L
+  })
+  print(f)
+  stopifnot(inherits(f, "MultiprocessFuture") || inherits(f, "UniprocessFuture"))
+
+  print(resolved(f))
+  y <- value(f)
+  print(y)
+  stopifnot(y == 42L)
+
+
+  ## A global variable
+  a <- 0
+  f <- multiprocess({
+    b <- 3
+    c <- 2
+    a * b * c
+  })
+  print(f)
+
+
+  ## A multiprocess future is evaluated in a separate
+  ## R process.  Changing the value of a global
+  ## variable should not affect the result of the
+  ## future.
+  a <- 7  ## Make sure globals are frozen
+  v <- value(f)
+  print(v)
+  stopifnot(v == 0)
+
+
+  message("*** multiprocess() with globals and blocking")
+  x <- listenv()
+  for (ii in 1:4) {
+    message(sprintf(" - Creating multiprocess future #%d ...", ii))
+    x[[ii]] <- multiprocess({ ii })
+  }
+  message(sprintf(" - Resolving %d multiprocess futures", length(x)))
+  v <- sapply(x, FUN=value)
+  stopifnot(all(v == 1:4))
+
+
+  message("*** multiprocess() and errors")
+  f <- multiprocess({
+    stop("Whoops!")
+    1
+  })
+  print(f)
+  v <- value(f, signal=FALSE)
+  print(v)
+  stopifnot(inherits(v, "simpleError"))
+
+  res <- try(value(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+
+  ## Error is repeated
+  res <- try(value(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+
+
+  message("*** multiprocess() - too large globals ...")
+  ooptsT <- options(future.globals.maxSize=1024*4L)
+
+  limit <- getOption("future.globals.maxSize")
+  cat(sprintf("Max total size of globals: %g bytes\n", limit))
+
+  for (workers in unique(c(1L, availableCores()))) {
+    message("Max number of processes: ", workers)
+
+    ## A large object
+    a <- 1:1014
+    yTruth <- sum(a)
+    size <- object.size(a)
+    cat(sprintf("a: %g bytes\n", size))
+    f <- multiprocess({ sum(a) }, workers=workers)
+    print(f)
+    rm(list="a")
+    v <- value(f)
+    print(v)
+    stopifnot(v == yTruth)
+
+
+    ## A too large object
+    a <- 1:1019 ## also on 32-bit platforms
+    yTruth <- sum(a)
+    size <- object.size(a)
+    cat(sprintf("a: %g bytes\n", size))
+    res <- try(f <- multiprocess({ sum(a) }, workers=workers), silent=TRUE)
+    rm(list="a")
+    stopifnot(inherits(res, "try-error"))
+  }
+
+  ## Undo options changed in this test
+  options(ooptsT)
+
+  message("*** multiprocess() - too large globals ... DONE")
+
+
+  message("*** multiprocess(..., workers=1L) ...")
+
+  a <- 2
+  b <- 3
+  yTruth <- a * b
+
+  f <- multiprocess({ a * b }, workers=1L)
+  rm(list=c("a", "b"))
+
+  v <- value(f)
+  print(v)
+  stopifnot(v == yTruth)
+
+  message("*** multiprocess(..., workers=1L) ... DONE")
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** multiprocess() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/multisession.R b/tests/multisession.R
new file mode 100644
index 0000000..8e8bc0c
--- /dev/null
+++ b/tests/multisession.R
@@ -0,0 +1,133 @@
+source("incl/start.R")
+library("listenv")
+plan(multisession)
+
+message("*** multisession() ...")
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  ## No global variables
+  f <- multisession({
+    42L
+  })
+  print(f)
+  stopifnot(inherits(f, "ClusterFuture") || inherits(f, "LazyFuture"))
+
+  print(resolved(f))
+  y <- value(f)
+  print(y)
+  stopifnot(y == 42L)
+
+
+  ## A global variable
+  a <- 0
+  f <- multisession({
+    b <- 3
+    c <- 2
+    a * b * c
+  })
+  print(f)
+
+
+  ## A multisession future is evaluated in a separate
+  ## R session process.  Changing the value of a global
+  ## variable should not affect the result of the
+  ## future.
+  a <- 7  ## Make sure globals are frozen
+  v <- value(f)
+  print(v)
+  stopifnot(v == 0)
+
+
+  message("*** multisession() with globals and blocking")
+  x <- listenv()
+  for (ii in 1:4) {
+    message(sprintf(" - Creating multisession future #%d ...", ii))
+    x[[ii]] <- multisession({ ii })
+  }
+  message(sprintf(" - Resolving %d multisession futures", length(x)))
+  v <- sapply(x, FUN=value)
+  stopifnot(all(v == 1:4))
+
+
+  message("*** multisession() and errors")
+  f <- multisession({
+    stop("Whoops!")
+    1
+  })
+  print(f)
+  v <- value(f, signal=FALSE)
+  print(v)
+  stopifnot(inherits(v, "simpleError"))
+
+  res <- try(value(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+
+  ## Error is repeated
+  res <- try(value(f), silent=TRUE)
+  print(res)
+  stopifnot(inherits(res, "try-error"))
+
+
+  message("*** multisession() - too large globals ...")
+  ooptsT <- options(future.globals.maxSize=1024*4L)
+
+  limit <- getOption("future.globals.maxSize")
+  cat(sprintf("Max total size of globals: %g bytes\n", limit))
+
+  for (workers in unique(c(1L, availableCores()))) {
+    message("Max number of sessions: ", workers)
+
+    ## A large object
+    a <- 1:1014
+    yTruth <- sum(a)
+    size <- object.size(a)
+    cat(sprintf("a: %g bytes\n", size))
+    f <- multisession({ sum(a) }, workers=workers)
+    print(f)
+    rm(list="a")
+    v <- value(f)
+    print(v)
+    stopifnot(v == yTruth)
+
+
+    ## A too large object
+    a <- 1:1019 ## also on 32-bit platforms
+    yTruth <- sum(a)
+    size <- object.size(a)
+    cat(sprintf("a: %g bytes\n", size))
+    res <- try(f <- multisession({ sum(a) }, workers=workers), silent=TRUE)
+    rm(list="a")
+    stopifnot(inherits(res, "try-error"))
+  }
+
+  ## Undo options changed in this test
+  options(ooptsT)
+
+  message("*** multisession() - too large globals ... DONE")
+
+
+  message("*** multisession(..., workers=1L) ...")
+
+  a <- 2
+  b <- 3
+  yTruth <- a * b
+
+  f <- multisession({ a * b }, workers=1L)
+  rm(list=c("a", "b"))
+
+  v <- value(f)
+  print(v)
+  stopifnot(v == yTruth)
+
+  message("*** multisession(..., workers=1L) ... DONE")
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** multisession() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/nbrOfWorkers.R b/tests/nbrOfWorkers.R
new file mode 100644
index 0000000..b4acfa1
--- /dev/null
+++ b/tests/nbrOfWorkers.R
@@ -0,0 +1,56 @@
+source("incl/start.R")
+
+message("*** nbrOfWorkers() ...")
+
+strategies <- c("eager", "lazy", "transparent")
+for (strategy in strategies) {
+  message("Type of future: ", strategy)
+
+  evaluator <- get(strategy, mode="function")
+  n <- nbrOfWorkers(evaluator)
+  message(sprintf("nbrOfWorkers: %d", n))
+  stopifnot(n == 1L)
+
+  plan(strategy)
+  n <- nbrOfWorkers()
+  message(sprintf("nbrOfWorkers: %d", n))
+  stopifnot(n == 1L)
+} ## for (strategy ...)
+
+
+strategies <- c("multiprocess", "multisession", "multicore")
+strategies <- intersect(strategies, supportedStrategies())
+cores <- availableCores()
+message("Number of available cores: ", cores)
+
+for (strategy in strategies) {
+  message("Type of future: ", strategy)
+
+  evaluator <- get(strategy, mode="function")
+  n <- nbrOfWorkers(evaluator)
+  message(sprintf("nbrOfWorkers: %d", n))
+  stopifnot(n == cores)
+
+  plan(strategy)
+  n <- nbrOfWorkers()
+  message(sprintf("nbrOfWorkers: %d", n))
+  stopifnot(n == cores)
+} ## for (strategy ...)
+
+
+message("Type of future: constant")
+n <- nbrOfWorkers(constant)
+message(sprintf("nbrOfWorkers: %d", n))
+stopifnot(n == 1)
+
+
+message("Type of future: <future>")
+foo <- structure(function(...) NULL, class=c("future"))
+n <- nbrOfWorkers(foo)
+message(sprintf("nbrOfWorkers: %g", n))
+stopifnot(n >= 0, is.infinite(n))
+
+
+message("*** nbrOfWorkers() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/nested_futures,mc.cores.R b/tests/nested_futures,mc.cores.R
new file mode 100644
index 0000000..ab2a77b
--- /dev/null
+++ b/tests/nested_futures,mc.cores.R
@@ -0,0 +1,93 @@
+source("incl/start.R")
+library("listenv")
+
+message("*** Nested futures - mc.cores ...")
+
+strategies <- c("multisession")
+if (supportsMulticore()) strategies <- c(strategies, "multicore")
+
+pid <- Sys.getpid()
+cat(sprintf("Main PID: %d\n", pid))
+
+cat("Available cores on this machine:\n")
+cores <- availableCores()
+print(cores)
+
+for (mc in 0:3) {
+  message(sprintf("- mc.cores=%d ...", mc))
+  options(mc.cores=mc)
+  mc2 <- min(mc, cores)
+  
+  for (strategy in strategies) {
+    message(sprintf("plan(list('eager', '%s')):", strategy))
+    plan(list('eager', strategy))
+    a %<-% {
+      b1 %<-% Sys.getpid()
+      b2 %<-% Sys.getpid()
+      list(pid=Sys.getpid(), cores=availableCores(), pid1=b1, pid2=b2)
+    }
+    print(a)
+    stopifnot(a$pid == pid)
+    stopifnot((mc2 <= 1 && a$pid1 == pid) || (a$pid1 != pid))
+    stopifnot((mc2 <= 1 && a$pid2 == pid) || (a$pid2 != pid))
+    stopifnot(((mc2 <= 1 || a$cores <= 2) && a$pid2 == a$pid1) || (a$pid2 != a$pid1))
+
+    message(sprintf("plan(list('eager', '%s':3)):", strategy))
+    plan(list('eager', tweak(strategy, workers=3)))
+    a %<-% {
+      b1 %<-% Sys.getpid()
+      b2 %<-% Sys.getpid()
+      list(pid=Sys.getpid(), cores=availableCores(), pid1=b1, pid2=b2)
+    }
+    print(a)
+    stopifnot(a$pid == pid)
+    stopifnot((mc2 <= 1 && a$pid1 == pid) || (a$pid1 != pid))
+    stopifnot((mc2 <= 1 && a$pid2 == pid) || (a$pid2 != pid))
+    stopifnot((mc2 <= 1 && a$pid2 == a$pid1) || (a$pid2 != a$pid1))
+
+    message(sprintf("plan(list('%s', 'eager')):", strategy))
+    plan(list(strategy, 'eager'))
+    a %<-% {
+      b1 %<-% Sys.getpid()
+      b2 %<-% Sys.getpid()
+      list(pid=Sys.getpid(), cores=availableCores(), pid1=b1, pid2=b2)
+    }
+    print(a)
+    stopifnot((mc2 <= 1 && a$pid  == pid) || (a$pid  != pid))
+    stopifnot((mc2 <= 1 && a$pid1 == pid) || (a$pid1 != pid))
+    stopifnot((mc2 <= 1 && a$pid2 == pid) || (a$pid2 != pid))
+    stopifnot(a$pid2 == a$pid1)
+
+    message(sprintf("plan(list('%s', '%s')):", strategy, strategy))
+    plan(list(strategy, strategy))
+    a %<-% {
+      b1 %<-% { Sys.sleep(1); Sys.getpid() }
+      b2 %<-% Sys.getpid()
+      list(pid=Sys.getpid(), cores=availableCores(), pid1=b1, pid2=b2)
+    }
+    print(a)
+    stopifnot((mc2 <= 1 && a$pid  == pid) || (a$pid  != pid))
+    stopifnot((mc2 <= 1 && a$pid1 == pid) || (a$pid1 != pid))
+    stopifnot((mc2 <= 1 && a$pid2 == pid) || (a$pid2 != pid))
+    stopifnot(a$pid2 == a$pid1)
+
+    message(sprintf("plan(list('%s':3, '%s':3)):", strategy, strategy))
+    plan(list(tweak(strategy, workers=3), tweak(strategy, workers=3)))
+    a %<-% {
+      b1 %<-% Sys.getpid()  ## This stalls
+      b2 %<-% Sys.getpid()
+      list(pid=Sys.getpid(), cores=availableCores(), pid1=b1, pid2=b2)
+    }
+    print(a)
+    stopifnot(a$pid  != pid)
+    stopifnot(a$pid1 != pid)
+    stopifnot(a$pid2 != pid)
+    stopifnot(a$pid2 != a$pid1)
+  } ## for (strategy ...)
+
+  message(sprintf(" - mc.cores=%d ... DONE", mc))
+} ## for (mc ...)
+
+message("*** Nested futures - mc.cores ... DONE")
+
+source("incl/end.R")
\ No newline at end of file
diff --git a/tests/plan.R b/tests/plan.R
new file mode 100644
index 0000000..fa03e02
--- /dev/null
+++ b/tests/plan.R
@@ -0,0 +1,239 @@
+source("incl/start,load-only.R")
+
+message("*** plan() ...")
+
+message("*** Set strategy via future::plan(future::lazy)")
+oplan <- future::plan(future::lazy)
+print(future::plan())
+future::plan(oplan)
+print(future::plan())
+
+message("*** Set strategy via future::plan(future::lazy, local=FALSE)")
+oplan <- future::plan(future::lazy, local=FALSE)
+print(future::plan())
+future::plan(oplan)
+print(future::plan())
+
+message("*** Set strategy via future::plan(future::lazy(local=FALSE)")
+oplan <- future::plan(future::lazy(local=FALSE))
+print(future::plan())
+future::plan(oplan)
+print(future::plan())
+
+message("*** Set strategy via future::plan('lazy')")
+oplan <- future::plan("lazy")
+print(future::plan())
+future::plan(oplan)
+print(future::plan())
+
+message("*** plan('default')")
+oplan <- future::plan("default")
+print(future::plan())
+future::plan(oplan)
+print(future::plan())
+
+
+library("future")
+
+message("*** plan('unknown strategy')")
+res <- try(plan('unknown strategy'), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+message("*** plan() by (lazy) function")
+
+## Setting strategy by function
+plan(lazy)
+a <- 0
+f <- future({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+a <- 7  ## Make sure globals are frozen
+##if ("covr" %in% loadedNamespaces()) v <- 0 else ## WORKAROUND
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+
+
+message("*** plan(eager)")
+plan(eager)
+a <- 0
+f <- future({
+  b <- 3
+  c <- 2
+  a * b * c
+})
+a <- 7
+v <- value(f)
+print(v)
+stopifnot(v == 0)
+
+
+message("*** plan('eager')")
+## Setting strategy by name
+plan("lazy")
+print(plan())
+
+
+message("*** plan() and overriding defaults")
+message("*** plan(eager)")
+plan(eager)
+fcn <- plan()
+print(fcn)
+stopifnot(formals(fcn)$local == TRUE)
+x <- 0
+f <- future({ x <- 1 })
+print(value(f))
+stopifnot(x == 0)
+
+message("*** plan(eager, local=FALSE)")
+plan(eager, local=FALSE)
+fcn <- plan()
+print(fcn)
+stopifnot(formals(fcn)$local == FALSE)
+x <- 0
+f <- future({ x <- 1 })
+print(value(f))
+stopifnot(x == 1)
+
+message("*** plan(eager, local=FALSE, abc=1, def=TRUE)")
+plan(eager, local=FALSE, abc=1, def=TRUE)
+fcn <- plan()
+print(fcn)
+stopifnot(formals(fcn)$local == FALSE)
+
+message("*** plan(eager(local=FALSE))")
+plan(lazy)
+plan(eager(local=FALSE))
+fcn <- plan()
+print(fcn)
+stopifnot(formals(fcn)$local == FALSE)
+
+message("*** plan(tweak(eager, local=FALSE))")
+plan(lazy)
+plan(tweak(eager, local=FALSE))
+fcn <- plan()
+print(fcn)
+stopifnot(formals(fcn)$local == FALSE)
+
+
+message("*** old <- plan(new)")
+truth <- plan()
+old <- plan(lazy, local=FALSE)
+stopifnot(identical(old, truth))
+
+curr <- plan()    ## curr == lazy(local=FALSE)
+prev <- plan(old) ## prev == lazy(local=FALSE)
+stopifnot(identical(curr, prev))
+
+curr <- plan()    ## curr == old
+stopifnot(identical(curr, old))
+stopifnot(identical(curr, truth))
+
+message("*** %plan% 'eager'")
+plan(lazy)
+x %<-% { a <- 1 } %plan% "eager"
+stopifnot(identical(body(plan()), body(lazy)))
+
+message("*** %plan% eager")
+plan(lazy)
+
+## %plan% can operate on any expression, so it
+## works just as an withPlan({ ... }, plan=...)
+fun <- { plan() } %plan% eager
+f <- fun(1)
+stopifnot(inherits(f, "EagerFuture"))
+
+x %<-% { a <- 1 } %plan% eager
+stopifnot(identical(body(plan()), body(lazy)))
+
+message("*** %plan% eager(local=FALSE) ")
+plan(lazy)
+a <- 0
+x %<-% { a } %plan% eager(local=FALSE)
+a <- 42
+print(x)
+stopifnot(x == 0)
+stopifnot(identical(body(plan()), body(lazy)))
+
+message("*** Nested futures with different plans ")
+plan(lazy)
+c %<-% {
+  message("Resolving 'c'")
+  a %<-% {
+    message("Resolving 'a'")
+    2
+  } %plan% eager
+  b %<-% {
+    message("Resolving 'b'")
+    -9 * a
+  }
+  message("Local variable 'x'")
+  x <- b / 3
+  abs(x)
+}
+d <- 42
+print(d)
+print(c)
+stopifnot(c == 6)
+
+message("*** plan() by functions and character names ... ")
+
+plan(eager)
+a %<-% 42
+stopifnot(a == 42)
+
+plan("eager")
+a %<-% 42
+stopifnot(a == 42)
+
+plan(list(eager))
+a %<-% 42
+stopifnot(a == 42)
+
+plan(list("eager"))
+a %<-% 42
+stopifnot(a == 42)
+
+plan(list(eager, lazy))
+a %<-% { b %<-% 42; b }
+stopifnot(a == 42)
+
+plan(list("eager", lazy))
+a %<-% { b %<-% 42; b }
+stopifnot(a == 42)
+
+plan(list(eager, "lazy"))
+a %<-% { b %<-% 42; b }
+stopifnot(a == 42)
+
+plan(list("eager", "lazy"))
+a %<-% { b %<-% 42; b }
+stopifnot(a == 42)
+
+message("*** plan() by functions and character names ... DONE")
+
+
+message("*** plan() w/ commands ...")
+
+plan(list(eager, eager))
+res <- plan("list")
+print(res)
+stopifnot(length(res) == 2)
+
+plan("pop")
+res <- plan("list")
+print(res)
+stopifnot(length(res) == 1)
+
+plan("reset")
+print(plan())
+
+message("*** plan() w/ commands ... DONE")
+
+
+message("*** plan() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/remote.R b/tests/remote.R
new file mode 100644
index 0000000..44e4bf5
--- /dev/null
+++ b/tests/remote.R
@@ -0,0 +1,54 @@
+source("incl/start.R")
+library("listenv")
+
+message("*** remote() ...")
+
+## No global variables
+f <- try(remote({
+  42L
+}, workers="localhost"), silent=FALSE)
+print(f)
+stopifnot(inherits(f, "ClusterFuture"))
+
+print(resolved(f))
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+plan(remote, workers="localhost")
+## No global variables
+f <- try(future({
+  42L
+}), silent=FALSE)
+print(f)
+stopifnot(inherits(f, "ClusterFuture"))
+
+print(resolved(f))
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+## A global variable
+a <- 0
+f <- try(future({
+  b <- 3
+  c <- 2
+  a * b * c
+}))
+print(f)
+
+
+message("*** remote() - exceptions ...")
+
+res <- try(remote(42L, workers=TRUE), silent=TRUE)
+print(res)
+stopifnot(inherits(res, "try-error"))
+
+message("*** remote() - exceptions ... DONE")
+
+
+message("*** remote() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/requestCore.R b/tests/requestCore.R
new file mode 100644
index 0000000..c6edf73
--- /dev/null
+++ b/tests/requestCore.R
@@ -0,0 +1,28 @@
+source("incl/start.R")
+
+message("*** requestCore() ...")
+
+message("*** requestCore() - exceptions ...")
+
+res <- try(requestCore(function() {}, workers=1L), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+res <- try(requestCore(function() {}, times=0L), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** requestCore() - exceptions ... DONE")
+
+
+message("*** requestCore() - timeout ...")
+
+plan(multicore, workers=2L)
+a %<-% { Sys.sleep(3); 1 }
+res <- try(requestCore(function() {}, workers=2L, times=1L, delta=0.1))
+stopifnot(inherits(res, "try-error"))
+stopifnot(a == 1)
+
+message("*** requestCore() - timeout ... DONE")
+
+message("*** requestCore() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/requestNode.R b/tests/requestNode.R
new file mode 100644
index 0000000..0195b86
--- /dev/null
+++ b/tests/requestNode.R
@@ -0,0 +1,28 @@
+source("incl/start.R")
+
+message("*** requestNode() ...")
+
+message("*** requestNode() - exceptions ...")
+
+res <- try(requestNode(function() {}, workers=1L), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+res <- try(requestNode(function() {}, times=0L), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** requestNode() - exceptions ... DONE")
+
+
+message("*** requestNode() - timeout ...")
+
+plan(multisession, workers=2L)
+f <- future({ Sys.sleep(3); 1 })
+
+res <- try(requestNode(function() {}, workers=f$workers, times=1L, delta=0.1))
+stopifnot(inherits(res, "try-error"))
+
+message("*** requestNode() - timeout ... DONE")
+
+message("*** requestNode() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/resolve.R b/tests/resolve.R
new file mode 100644
index 0000000..560e8bb
--- /dev/null
+++ b/tests/resolve.R
@@ -0,0 +1,293 @@
+source("incl/start.R")
+library("listenv")
+
+oopts <- c(oopts, options(future.progress=TRUE))
+plan(lazy)
+
+strategies <- supportedStrategies()
+strategies <- setdiff(strategies, "multiprocess")
+
+message("*** resolve() ...")
+
+
+message("*** resolve() for Future objects ...")
+
+plan(multisession, workers=2L)
+
+for (value in c(FALSE, TRUE)) {
+  for (recursive in list(FALSE, TRUE, -1, 0, 1, 2, Inf)) {
+    message(sprintf("- value=%s, recursive=%s ...", value, recursive))
+  
+    f <- future({
+      Sys.sleep(0.5)
+      list(a=1, b=42L)
+    })
+    res <- resolve(f, value=value, recursive=recursive)
+    stopifnot(identical(res, f))
+
+    message("- w/ exception ...")
+    f <- future(list(a=1, b=42L, c=stop("Nah!")))
+    res <- resolve(f, value=value, recursive=recursive)
+    stopifnot(identical(res, f))
+
+    message(sprintf("- value=%s, recursive=%s ... DONE", value, recursive))
+  } ## for (resolve ...)
+} ## for (value ...)
+
+message("- exception ... DONE")
+
+message("*** resolve() for Future objects ... DONE")
+
+
+message("*** resolve() for lists ...")
+
+for (strategy in strategies) {
+  message(sprintf("- plan('%s') ...", strategy))
+  plan(strategy)
+
+  x <- list()
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+
+  x <- list()
+  x$a <- 1
+  x$b <- 2
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+
+  x <- list()
+  x$a <- future(1)
+  x$b <- future(2)
+  x[[3]] <- 3
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+  stopifnot(resolved(x$a))
+  stopifnot(resolved(x[["b"]]))
+
+  x <- list()
+  x$a <- future(1)
+  x$b <- future({Sys.sleep(1); 2})
+  x[[4]] <- 4
+  dim(x) <- c(2,2)
+  y <- resolve(x, idxs=1)
+  stopifnot(identical(y, x))
+  stopifnot(resolved(x[[1]]))
+  y <- resolve(x, idxs=2)
+  stopifnot(identical(y, x))
+  stopifnot(resolved(x[[2]]))
+  y <- resolve(x, idxs=3)
+  stopifnot(identical(y, x))
+  y <- resolve(x, idxs=seq_along(x))
+  stopifnot(identical(y, x))
+  y <- resolve(x, idxs=names(x))
+  stopifnot(identical(y, x))
+
+  y <- resolve(x, idxs=matrix(c(1,2), ncol=2L), value=TRUE)
+  stopifnot(identical(y, x))
+
+  x <- list()
+  for (kk in 1:3) x[[kk]] <- future({ Sys.sleep(1); kk })
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+
+  ## Exceptions
+  x <- list()
+  x$a <- 1
+  x$b <- 2
+
+  res <- try(y <- resolve(x, idxs=0L), silent=TRUE)
+  stopifnot(inherits(res, "try-error"))
+
+  res <- try(y <- resolve(x, idxs="unknown"), silent=TRUE)
+  stopifnot(inherits(res, "try-error"))
+
+  x <- list(1, 2)
+  res <- try(x <- resolve(x, idxs="a"))
+  stopifnot(inherits(res, "try-error"))
+
+  message(sprintf("- plan('%s') ...", strategy))
+} ## for (strategy ...)
+
+
+message("*** resolve() for lists ... DONE")
+
+
+message("*** resolve() for environments ...")
+
+for (strategy in strategies) {
+  message(sprintf("- plan('%s') ...", strategy))
+  plan(strategy)
+
+  x <- new.env()
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+
+  x <- new.env()
+  x$a <- 1
+  x$b <- 2
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 0L)
+
+  x <- new.env()
+  x$a <- future(1)
+  x$b <- future(2)
+  x$c <- 3
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+  stopifnot(resolved(x$a))
+  stopifnot(resolved(x$b))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+
+  x <- new.env()
+  x$a %<-% { 1 }
+  x$b %<-% { 2 }
+  x$c <- 3
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x)  ## FIXME: Should not do value()!
+  stopifnot(identical(y, x))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+
+  x <- new.env()
+  x$a <- future({ 1 })
+  x$b %<-% { 2 }
+  x$c <- 3
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x, idxs="a")
+  stopifnot(identical(y, x))
+  stopifnot(resolved(x$a))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x, idxs="b")
+  stopifnot(identical(y, x))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x, idxs="c")
+  stopifnot(identical(y, x))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x, idxs=names(x), value=TRUE)
+  stopifnot(identical(y, x))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x, recursive=TRUE, value=TRUE)
+  stopifnot(identical(y, x))
+
+  ## Exceptions
+  res <- try(y <- resolve(x, idxs="unknown"), silent=TRUE)
+  stopifnot(inherits(res, "try-error"))
+
+  message(sprintf("- plan('%s') ...", strategy))
+} ## for (strategy ...)
+
+message("*** resolve() for environments ... DONE")
+
+
+message("*** resolve() for list environments ...")
+
+for (strategy in strategies) {
+  message(sprintf("- plan('%s') ...", strategy))
+  plan(strategy)
+
+  options(future.progress=function(done, total) {
+    msg <- sprintf("Wohoo: %.0f%% (%d/%d)", 100*done/total, done, total)
+    if (done < total) {
+      bs <- paste(rep("\b", times=nchar(msg)), collapse="")
+      message(paste(msg, bs, sep=""), appendLF=FALSE)
+    } else {
+      message(msg)
+    }
+  })
+
+
+  x <- listenv()
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+
+  x <- listenv()
+  x$a <- 1
+  x$b <- 2
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 0L)
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+
+  x <- listenv()
+  x$a <- future(1)
+  x$b <- future(2)
+  x$c <- 3
+  names <- names(x)
+  dim(x) <- c(1,3)
+  names(x) <- names
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x)
+  stopifnot(identical(y, x))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+
+  x <- listenv()
+  x$a %<-% { 1 }
+  x$b %<-% { 2 }
+  x$c <- 3
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+  y <- resolve(x)  ## FIXME: Should not do value()!
+  stopifnot(identical(y, x))
+  #stopifnot(is.na(futureOf(x$a, mustExist=FALSE)))
+  #stopifnot(is.na(futureOf(x$b, mustExist=FALSE)))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 2L)
+
+  x <- listenv()
+  x$a <- future({ 1 })
+  x$b %<-% { Sys.sleep(1); 2 }
+  x$c %<-% { 3 }
+  x$d <- 4
+  names <- names(x)
+  dim(x) <- c(2,2)
+  names(x) <- names
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 3L)
+  y <- resolve(x, idxs="a")
+  stopifnot(identical(y, x))
+  stopifnot(identical(futureOf(x$a, mustExist=FALSE), x$a))
+  stopifnot(resolved(x$a))
+  y <- resolve(x, idxs="b")
+  stopifnot(identical(y, x))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 3L)
+
+  idxs <- matrix(c(1,2), ncol=2L)
+  y <- resolve(x, idxs=idxs)
+  stopifnot(identical(y, x))
+  #stopifnot(is.na(futureOf(x$c, mustExist=FALSE)))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 3L)
+
+  y <- resolve(x, idxs=4L)
+  stopifnot(identical(y, x))
+  #stopifnot(is.na(futureOf(x[[4L]], mustExist=FALSE)))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 3L)
+
+  y <- resolve(x, idxs=names(x), value=TRUE)
+  stopifnot(identical(y, x))
+  stopifnot(length(futureOf(envir=x, drop=TRUE)) == 3L)
+
+  y <- resolve(x, recursive=TRUE, value=TRUE)
+  stopifnot(identical(y, x))
+
+  ## Exceptions
+  res <- try(y <- resolve(x, idxs=0L), silent=TRUE)
+  stopifnot(inherits(res, "try-error"))
+
+  res <- try(y <- resolve(x, idxs="unknown"), silent=TRUE)
+  stopifnot(inherits(res, "try-error"))
+
+  message(sprintf("- plan('%s') ...", strategy))
+} ## for (strategy ...)
+
+message("*** resolve() for list environments ... DONE")
+
+
+
+message("*** resolved() - default ...")
+
+res <- resolved(42L)
+stopifnot(isTRUE(res))
+
+message("*** resolved() - default ... DONE")
+
+
+message("*** resolve() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/rng.R b/tests/rng.R
new file mode 100644
index 0000000..2a89ff2
--- /dev/null
+++ b/tests/rng.R
@@ -0,0 +1,94 @@
+source("incl/start.R")
+library("future")
+
+message("*** rng ...")
+
+## See Section 6 on 'Random-number generation' in
+## vignette("parallel", package="parallel")
+fsample <- function(x, size=4L, seed=NULL) {
+  oseed <- .GlobalEnv$.Random.seed
+  orng <- RNGkind("L'Ecuyer-CMRG")[1L]
+  on.exit(RNGkind(orng))
+
+  if (!is.null(seed)) {
+    ## Reset state of random seed afterwards?
+    on.exit({
+      if (is.null(oseed)) {
+        rm(list=".Random.seed", envir=.GlobalEnv, inherits=FALSE)
+      } else {
+        .GlobalEnv$.Random.seed <- oseed
+      }
+    }, add=TRUE)
+
+    set.seed(seed)
+  }
+
+  .seed <- .Random.seed
+  res <- listenv::listenv()
+  for (ii in seq_len(size)) {
+    .seed <- parallel::nextRNGStream(.seed)
+    res[[ii]] %<-% {
+      .GlobalEnv$.Random.seed <- .seed
+      sample(x, size=1L)
+    }
+  }
+  unlist(res)
+} # fsample()
+
+
+dummy <- sample(0:9, size=1L)
+seed0 <- .Random.seed
+
+## Reference sample with fixed random seed
+plan("eager")
+y0 <- fsample(0:9, seed=42L)
+
+## Assert that random seed is reset
+stopifnot(identical(.GlobalEnv$.Random.seed, seed0))
+
+
+for (cores in 1:min(3L, availableCores())) {
+  message(sprintf("Testing with %d cores ...", cores))
+  options(mc.cores=cores-1L)
+
+  for (strategy in supportedStrategies()) {
+    message(sprintf("%s ...", strategy))
+
+    .GlobalEnv$.Random.seed <- seed0
+
+    plan(strategy)
+
+    ## Fixed random seed
+    y1 <- fsample(0:9, seed=42L)
+    print(y1)
+    stopifnot(identical(y1, y0))
+
+    ## Assert that random seed is reset
+    stopifnot(identical(.GlobalEnv$.Random.seed, seed0))
+
+    ## Fixed random seed
+    y2 <- fsample(0:9, seed=42L)
+    print(y2)
+    stopifnot(identical(y2, y1))
+    stopifnot(identical(y2, y0))
+
+    ## Assert that random seed is reset
+    stopifnot(identical(.GlobalEnv$.Random.seed, seed0))
+
+    ## No seed
+    y3 <- fsample(0:9)
+    print(y3)
+
+    ## No seed
+    y4 <- fsample(0:9)
+    print(y4)
+
+    message(sprintf("%s ... done", strategy))
+  }
+
+  message(sprintf("Testing with %d cores ... DONE", cores))
+} ## for (cores ...)
+
+message("*** rng ... DONE")
+
+source("incl/end.R")
diff --git a/tests/startup.R b/tests/startup.R
new file mode 100644
index 0000000..92a61b2
--- /dev/null
+++ b/tests/startup.R
@@ -0,0 +1,238 @@
+source("incl/start.R")
+
+maxCores <- min(2L, availableCores(methods="system"))
+
+
+plan("default")
+strategy0 <- plan()
+ 
+message("*** parseCmdArgs() ...")
+
+args <- parseCmdArgs()
+str(args)
+
+options(future.plan=NULL, future.cmdargs=c("-p", 1L))
+args <- parseCmdArgs()
+str(args)
+stopifnot(args$p == 1L)
+
+options(future.plan=NULL, future.cmdargs=c(sprintf("--parallel=%d", maxCores)))
+args <- parseCmdArgs()
+str(args)
+stopifnot(args$p == maxCores)
+
+options(future.plan=NULL, future.cmdargs=c("-p", 1L, sprintf("--parallel=%d", maxCores)))
+args <- parseCmdArgs()
+str(args)
+stopifnot(args$p == maxCores)
+
+options(future.plan=NULL, future.cmdargs=c("-p", 0L))
+args <- parseCmdArgs()
+stopifnot(is.null(args$p))
+res <- tryCatch(parseCmdArgs(), warning=function(w) w)
+stopifnot(inherits(res, "warning"))
+
+options(future.plan=NULL, future.cmdargs=c("-p", .Machine$integer.max))
+args <- parseCmdArgs()
+stopifnot(is.null(args$p))
+res <- tryCatch(parseCmdArgs(), warning=function(w) w)
+stopifnot(inherits(res, "warning"))
+
+options(future.plan=NULL, future.cmdargs=NULL)
+
+message("*** parseCmdArgs() ... DONE")
+
+
+
+message("*** .onLoad() ...")
+plan("default")
+pkgname <- "future"
+
+message("- .onLoad() w/out command-line options ...")
+options(future.plan=NULL, future.cmdargs=NULL)
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(all(class(strategy) == class(strategy0)))
+plan("default")
+message("- .onLoad() w/out command-line options ... DONE")
+
+message("- .onLoad() w/ -p 1 ...")
+options(future.plan=NULL, future.cmdargs=c("-p", 1))
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(inherits(strategy, "eager"))
+plan("default")
+message("- .onLoad() w/ -p 1 ... DONE")
+
+message("- .onLoad() w/ --parallel=1 ...")
+plan("default")
+options(future.plan=NULL, future.cmdargs="-parallel=1")
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(inherits(strategy, "eager"))
+plan("default")
+message("- .onLoad() w/ --parallel=1 ... DONE")
+
+message("- .onLoad() w/ -p 2 ...")
+options(future.plan=NULL, future.cmdargs=c("-p", 2))
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+if (maxCores >= 2) {
+  stopifnot(inherits(strategy, "multiprocess"))
+} else {
+  stopifnot(all(class(strategy) == class(strategy0)))
+}
+plan("default")
+message("- .onLoad() w/ -p 2 ... DONE")
+
+message("- .onLoad() w/ -p 0 ...")
+options(future.plan=NULL, future.cmdargs=c("-p", 0))
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(all(class(strategy) == class(strategy0)))
+plan("default")
+message("- .onLoad() w/ -p 0 ... DONE")
+
+message("- .onLoad() w/ -p -1 ...")
+options(future.plan=NULL, future.cmdargs=c("-p", -1))
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(all(class(strategy) == class(strategy0)))
+plan("default")
+message("- .onLoad() w/ -p -1 ... DONE")
+
+message("- .onLoad() w/ -p foo ...")
+options(future.plan=NULL, future.cmdargs=c("-p", "foo"))
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(all(class(strategy) == class(strategy0)))
+plan("default")
+message("- .onLoad() w/ -p foo ... DONE")
+
+message("- .onLoad() w/ R_FUTURE_PLAN='lazy' ...")
+Sys.setenv("R_FUTURE_PLAN"="lazy")
+options(future.plan=NULL, future.cmdargs=NULL)
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(inherits(strategy, "lazy"))
+plan("default")
+Sys.setenv("R_FUTURE_PLAN"="")
+message("- .onLoad() w/ R_FUTURE_PLAN='lazy' ... DONE")
+
+message("- .onLoad() w/ future.plan='lazy' ...")
+options(future.plan=NULL, future.plan='lazy', future.cmdargs=NULL)
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(inherits(strategy, "lazy"))
+plan("default")
+message("- .onLoad() w/ future.plan='lazy' ... DONE")
+
+message("- .onLoad() w/ R_FUTURE_PLAN='lazy' & -p 1 ...")
+Sys.setenv("R_FUTURE_PLAN"="lazy")
+options(future.plan=NULL, future.cmdargs=c("-p", 1))
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(inherits(strategy, "lazy"))
+plan("default")
+Sys.setenv("R_FUTURE_PLAN"="")
+message("- .onLoad() w/ R_FUTURE_PLAN='lazy' & -p 1 ... DONE")
+
+message("- .onLoad() w/ future.plan='lazy' & -p 1 ...")
+options(future.plan='lazy', future.cmdargs=c("-p", "1"))
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(inherits(strategy, "lazy"))
+plan("default")
+message("- .onLoad() w/ future.plan='lazy' & -p 1 ... DONE")
+
+message("- .onLoad() w/ future.plan='lazy' & -p 1 ...")
+options(future.plan=lazy, future.cmdargs=c("-p", "1"))
+.onLoad(pkgname, pkgname)
+strategy <- plan()
+print(strategy)
+stopifnot(inherits(strategy, "lazy"))
+plan("default")
+message("- .onLoad() w/ future.plan='lazy' & -p 1 ... DONE")
+
+
+message("- .onLoad() w/ future.availableCores.system=1L ...")
+options(future.availableCores.system=1L)
+.onLoad(pkgname, pkgname)
+options(future.availableCores.system=NULL)
+message("- .onLoad() w/ future.availableCores.system=1L ... DONE")
+
+message("- .onLoad() w/ R_FUTURE_AVAILABLECORES_SYSTEM ...")
+Sys.setenv("R_FUTURE_AVAILABLECORES_SYSTEM"="1")
+.onLoad(pkgname, pkgname)
+ncores <- getOption("future.availableCores.system")
+print(ncores)
+stopifnot(is.integer(ncores), ncores == 1L)
+Sys.unsetenv("R_FUTURE_AVAILABLECORES_SYSTEM")
+options(future.availableCores.system=NULL)
+
+Sys.setenv("R_FUTURE_AVAILABLECORES_SYSTEM"="NA")
+.onLoad(pkgname, pkgname)
+ncores <- getOption("future.availableCores.system")
+print(ncores)
+stopifnot(is.integer(ncores), is.na(ncores))
+Sys.unsetenv("R_FUTURE_AVAILABLECORES_SYSTEM")
+options(future.availableCores.system=NULL)
+
+Sys.setenv("R_FUTURE_AVAILABLECORES_SYSTEM"="NA_real_")
+.onLoad(pkgname, pkgname)
+ncores <- getOption("future.availableCores.system")
+print(ncores)
+stopifnot(is.integer(ncores), is.na(ncores))
+Sys.unsetenv("R_FUTURE_AVAILABLECORES_SYSTEM")
+options(future.availableCores.system=NULL)
+
+message("- .onLoad() w/ R_FUTURE_AVAILABLECORES_SYSTEM ... DONE")
+
+
+options(future.plan=NULL, future.cmdargs=NULL, future.availableCores.system=1L)
+
+options(future.plan=NULL, future.cmdargs=NULL, future.availableCores.system=NULL)
+
+message("*** .onLoad() ... DONE")
+
+
+message("*** .onAttach() ...")
+
+pkgname <- "future"
+
+message("- .onAttach() w/ option future.startup.loadScript ...")
+
+for (value in list(NULL, FALSE, TRUE)) {
+  options(future.startup.loadScript=value)
+  .onAttach(pkgname, pkgname)
+}
+
+message("- .onAttach() w/ option future.startup.loadScript ... DONE")
+
+message("- .onAttach() with ./.future.R ...")
+
+pathname <- ".future.R"
+xyz <- 0L
+cat("xyz <- 42L; cat('ping\n')\n", file=pathname)
+.onAttach(pkgname, pkgname)
+print(xyz)
+stopifnot(is.integer(xyz), xyz >= 0, xyz == 42L)
+file.remove(pathname)
+
+message("- .onAttach() with ./.future.R ... DONE")
+
+message("*** .onAttach() ... DONE")
+
+
+source("incl/end.R")
diff --git a/tests/transparent.R b/tests/transparent.R
new file mode 100644
index 0000000..5269842
--- /dev/null
+++ b/tests/transparent.R
@@ -0,0 +1,44 @@
+source("incl/start.R")
+library("listenv")
+
+message("*** transparent() ...")
+
+## No global variables
+f <- try(transparent({
+  42L
+}), silent=FALSE)
+print(f)
+stopifnot(inherits(f, "EagerFuture"))
+
+print(resolved(f))
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+plan(transparent)
+## No global variables
+f <- try(future({
+  42L
+}), silent=FALSE)
+print(f)
+stopifnot(inherits(f, "EagerFuture"))
+
+print(resolved(f))
+y <- value(f)
+print(y)
+stopifnot(y == 42L)
+
+
+## A global variable
+a <- 0
+f <- try(future({
+  b <- 3
+  c <- 2
+  a * b * c
+}))
+print(f)
+
+message("*** transparent() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/tweak.R b/tests/tweak.R
new file mode 100644
index 0000000..209a860
--- /dev/null
+++ b/tests/tweak.R
@@ -0,0 +1,121 @@
+source("incl/start,load-only.R")
+
+message("*** Tweaking future strategies ...")
+
+message("*** y <- tweak(future::lazy) ...")
+lazy2 <- future::tweak(future::lazy)
+print(args(lazy2))
+stopifnot(identical(lazy2, future::lazy))
+stopifnot(!inherits(lazy2, "tweaked"))
+
+
+message("*** y <- tweak(future::lazy, local=FALSE) ...")
+lazy2 <- future::tweak(future::lazy, local=FALSE)
+print(args(lazy2))
+stopifnot(!identical(lazy2, future::lazy))
+stopifnot(inherits(lazy2, "tweaked"))
+stopifnot(identical(formals(lazy2)$local, FALSE))
+
+
+message("*** y <- tweak('lazy', local=FALSE) ...")
+lazy2 <- future::tweak("lazy", local=FALSE)
+print(args(lazy2))
+stopifnot(!identical(lazy2, future::lazy))
+stopifnot(inherits(lazy2, "tweaked"))
+stopifnot(identical(formals(lazy2)$local, FALSE))
+
+
+library("future")
+
+message("*** y <- tweak(lazy, local=FALSE) ...")
+lazy2 <- future::tweak(lazy, local=FALSE)
+print(args(lazy2))
+stopifnot(!identical(lazy2, future::lazy))
+stopifnot(inherits(lazy2, "tweaked"))
+stopifnot(identical(formals(lazy2)$local, FALSE))
+
+message("*** y <- tweak('lazy', local=FALSE) ...")
+lazy2 <- future::tweak('lazy', local=FALSE)
+print(args(lazy2))
+stopifnot(!identical(lazy2, future::lazy))
+stopifnot(inherits(lazy2, "tweaked"))
+stopifnot(identical(formals(lazy2)$local, FALSE))
+
+message("*** y <- tweak('lazy', local=FALSE, abc=1, def=TRUE) ...")
+res <- tryCatch({
+  lazy2 <- future::tweak('lazy', local=FALSE, abc=1, def=TRUE)
+}, warning=function(w) {
+  w
+})
+stopifnot(inherits(res, "warning"))
+lazy2 <- future::tweak('lazy', local=FALSE, abc=1, def=TRUE)
+print(args(lazy2))
+stopifnot(!identical(lazy2, future::lazy))
+stopifnot(inherits(lazy2, "tweaked"))
+stopifnot(identical(formals(lazy2)$local, FALSE))
+
+
+message("*** y %<-% { expr } %tweak% tweaks ...")
+
+plan(eager)
+a <- 0
+
+x %<-% { a <- 1; a }
+print(x)
+stopifnot(a == 0, x == 1)
+
+x %<-% { a <- 2; a } %tweak% list(local=FALSE)
+print(x)
+stopifnot(a == 2, x == 2)
+
+
+plan(eager, local=FALSE)
+a <- 0
+
+x %<-% { a <- 1; a }
+print(x)
+stopifnot(a == 1, x == 1)
+
+x %<-% { a <- 2; a } %tweak% list(local=TRUE)
+print(x)
+stopifnot(a == 1, x == 2)
+
+
+# Preserve nested futures
+plan(list(A=eager, B=tweak(eager, local=FALSE)))
+a <- 0
+
+x %<-% {
+  stopifnot(identical(names(plan("list")), "B"))
+  a <- 1
+  a
+}
+print(x)
+stopifnot(a == 0, x == 1)
+
+x %<-% {
+  stopifnot(identical(names(plan("list")), "B"))
+  a <- 2
+  a
+} %tweak% list(local=FALSE)
+print(x)
+stopifnot(a == 2, x == 2)
+
+
+message("*** y %<-% { expr } %tweak% tweaks ... DONE")
+
+
+message("*** tweak() - exceptions ...")
+
+res <- try(tweak("<unknown-future-strategy>"), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+res <- try(tweak(eager, "unnamed-argument"), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** tweak() - exceptions ... DONE")
+
+
+message("*** Tweaking future strategies ... DONE")
+
+source("incl/end.R")
diff --git a/tests/utils.R b/tests/utils.R
new file mode 100644
index 0000000..00c7afa
--- /dev/null
+++ b/tests/utils.R
@@ -0,0 +1,178 @@
+source("incl/start,load-only.R")
+
+message("*** utils ...")
+
+message("*** hpaste() ...")
+
+# Some vectors
+x <- 1:6
+y <- 10:1
+z <- LETTERS[x]
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Abbreviation of output vector
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+printf("x = %s.\n", hpaste(x))
+## x = 1, 2, 3, ..., 6.
+
+printf("x = %s.\n", hpaste(x, maxHead=2))
+## x = 1, 2, ..., 6.
+
+printf("x = %s.\n", hpaste(x), maxHead=3) # Default
+## x = 1, 2, 3, ..., 6.
+
+# It will never output 1, 2, 3, 4, ..., 6
+printf("x = %s.\n", hpaste(x, maxHead=4))
+## x = 1, 2, 3, 4, 5 and 6.
+
+# Showing the tail
+printf("x = %s.\n", hpaste(x, maxHead=1, maxTail=2))
+## x = 1, ..., 5, 6.
+
+# Turning off abbreviation
+printf("y = %s.\n", hpaste(y, maxHead=Inf))
+## y = 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
+
+## ...or simply
+printf("y = %s.\n", paste(y, collapse=", "))
+## y = 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Adding a special separator before the last element
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Change last separator
+printf("x = %s.\n", hpaste(x, lastCollapse=" and "))
+## x = 1, 2, 3, 4, 5 and 6.
+
+message("*** hpaste() ...")
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# asIEC()
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+message("*** asIEC() ...")
+
+for (size in c(0, 10^(0:20))) {
+  cat(sprintf("Size: %.f bytes = %s\n", size, asIEC(size)))
+}
+
+message("*** asIEC() ... DONE")
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# debug()
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+message("*** mdebug() ...")
+
+mdebug("Hello #1")
+options(future.debug=TRUE)
+mdebug("Hello #2")
+options(future.debug=FALSE)
+mdebug("Hello #3")
+
+message("*** mdebug() ... DONE")
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# geval() et al.
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+message("*** geval() et al. ...")
+
+gls <- function(..., envir=.GlobalEnv) ls(..., envir=envir)
+
+message("- gls() ...")
+genv <- new.env(parent=globalenv())
+vars <- gls(envir=genv)
+print(vars)
+stopifnot(length(vars) == 0)
+
+message("- gassign() ...")
+gassign("a", 1, envir=genv)
+vars <- gls(envir=genv)
+print(vars)
+stopifnot(length(vars) == 1)
+
+message("- grmall() ...")
+grmall(envir=genv)
+vars <- gls(envir=genv)
+print(vars)
+stopifnot(length(vars) == 0)
+
+message("- geval() ...")
+gassign("a", 1, envir=genv)
+res <- geval(substitute(a), envir=genv)
+print(res)
+vars <- gls(envir=genv)
+print(vars)
+stopifnot(length(vars) == 1)
+
+
+message("*** geval() et al. ... DONE")
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# requirePackages()
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+message("*** requirePackages() ...")
+
+res <- requirePackages("future")
+res <- requirePackages(c("future", "listenv"))
+
+res <- try(requirePackages("<unknown package>"), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** requirePackages() ... DONE")
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# importParallel()
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+message("*** importParallel() ...")
+
+mclapply <- importParallel("mclapply")
+stopifnot(identical(mclapply, parallel::mclapply))
+
+ns <- getNamespace("parallel")
+if (exists("sendCall", envir=ns, mode="function")) {
+  sendCall <- importParallel("sendCall")
+  stopifnot(identical(sendCall, parallel:::sendCall))
+} else {
+  res <- try(importParallel("sendCall"), silent=TRUE)
+  stopifnot(inherits(res, "try-error"))
+}
+
+res <- try(importParallel("<unknown function>"), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** importParallel() ... DONE")
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# myInternalIP() and myExternalIP()
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+message("*** myInternalIP() ...")
+ips <- myInternalIP(mustWork=FALSE)
+message("myInternalIP(): ", paste(ips, collapse=", "))
+message("*** myInternalIP() ... DONE")
+
+ips <- myInternalIP(force=TRUE, which="first", mustWork=FALSE)
+message("myInternalIP(which='first'): ", paste(ips, collapse=", "))
+message("*** myInternalIP() ... DONE")
+
+ips <- myInternalIP(force=TRUE, which="last", mustWork=FALSE)
+message("myInternalIP(which='last'): ", paste(ips, collapse=", "))
+message("*** myInternalIP() ... DONE")
+
+ips <- myInternalIP(force=TRUE, which="all", mustWork=FALSE)
+message("myInternalIP(which='all'): ", paste(ips, collapse=", "))
+message("*** myInternalIP() ... DONE")
+
+message("*** myExternalIP() ...")
+ip <- myExternalIP(mustWork=FALSE)
+message("myExternalIP(): ", ip)
+message("*** myExternalIP() ... DONE")
+
+
+message("*** utils ... DONE")
+
+source("incl/end.R")
diff --git a/tests/uuid.R b/tests/uuid.R
new file mode 100644
index 0000000..a59b0f9
--- /dev/null
+++ b/tests/uuid.R
@@ -0,0 +1,18 @@
+source("incl/start.R")
+uuid <- future:::uuid
+
+message("*** uuid() ...")
+
+id0 <- uuid()
+print(id0)
+
+## Reset UUID (hack)
+environment(uuid)$value <- NULL
+
+id <- uuid()
+print(id)
+stopifnot(id != id0)
+
+message("*** uuid() ... DONE")
+
+source("incl/end.R")
diff --git a/tests/whichIndex.R b/tests/whichIndex.R
new file mode 100644
index 0000000..4bc0e55
--- /dev/null
+++ b/tests/whichIndex.R
@@ -0,0 +1,77 @@
+source("incl/start,load-only.R")
+
+message("*** whichIndex() ...")
+
+dims <- list(
+  c(1),
+  c(1,1),
+  c(2),
+  c(2,1),
+  c(3,4,3)
+)
+
+for (dim in dims) {
+  printf("Dimensions: (%s)\n", paste(dim, collapse=", "))
+  dimnames <- lapply(dim, FUN=function(n) letters[seq_len(n)])
+  X <- array(seq_len(prod(dim)), dim=dim, dimnames=dimnames)
+  print(X)
+
+  idxs <- unique(round(seq(from=1L, to=length(X), length.out=5)))
+  print(idxs)
+  stopifnot(all(X[idxs] == idxs))
+
+  ## (a) By matrix and dimindices
+  I <- arrayInd(idxs, .dim=dim(X))
+  print(I)
+  idxs2 <- whichIndex(I, dim=dim(X))
+  print(idxs2)
+  stopifnot(all(idxs2 == idxs))
+
+  ## (b) By matrix and dimnames
+  N <- array(NA_character_, dim=dim(I))
+  for (kk in seq_len(ncol(N))) {
+    N[,kk] <- dimnames[[kk]][I[,kk]]
+  }
+  print(N)
+  idxs3 <- whichIndex(N, dim=dim(X), dimnames=dimnames(X))
+  print(idxs3)
+  stopifnot(all(idxs3 == idxs))
+
+  ## (b) By data.frame
+  D <- as.data.frame(I)
+  for (cc in seq(from=1L, to=ncol(D))) D[[cc]] <- N[,cc]
+  print(D)
+  idxs4 <- whichIndex(D, dim=dim(X), dimnames=dimnames(X))
+  print(idxs4)
+  stopifnot(all(idxs4 == idxs))
+}
+
+
+## Exceptions
+dim <- c(2,3)
+ndim <- length(dim)
+dimnames <- lapply(dim, FUN=function(n) letters[seq_len(n)])
+
+I <- matrix(c(1,1,2,4), ncol=ndim)
+res <- try(idxs <- whichIndex(I, dim=dim, dimnames=dimnames), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+I <- matrix(c(0,0), ncol=ndim)
+res <- try(idxs <- whichIndex(I, dim=dim, dimnames=dimnames), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+I <- matrix(c("a","q"), ncol=ndim)
+res <- try(idxs <- whichIndex(I, dim=dim, dimnames=dimnames), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+D <- data.frame(a=c(1,1), b=c(2,4))
+res <- try(idxs <- whichIndex(D, dim=dim, dimnames=dimnames), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+D <- data.frame(a=c("a","q"), b=c(1,2))
+res <- try(idxs <- whichIndex(D, dim=dim, dimnames=dimnames), silent=TRUE)
+stopifnot(inherits(res, "try-error"))
+
+message("*** whichIndex() ... DONE")
+
+source("incl/end.R")
diff --git a/vignettes/future-2-issues.md.rsp b/vignettes/future-2-issues.md.rsp
new file mode 100644
index 0000000..bd916df
--- /dev/null
+++ b/vignettes/future-2-issues.md.rsp
@@ -0,0 +1,322 @@
+<%@meta language="R-vignette" content="--------------------------------
+%\VignetteIndexEntry{A Future for R: Common Issues with Solutions}
+%\VignetteAuthor{Henrik Bengtsson}
+%\VignetteKeyword{R}
+%\VignetteKeyword{package}
+%\VignetteKeyword{vignette}
+%\VignetteKeyword{future}
+%\VignetteKeyword{promise}
+%\VignetteEngine{R.rsp::rsp}
+%\VignetteTangle{FALSE}
+--------------------------------------------------------------------"%>
+# <%@meta name="title"%>
+
+In the ideal case, all it takes to start using futures in R is to replace select standard assignments (`<-`) in your R code with future assignments (`%<-%`) and make sure the right-hand side (RHS) expressions are within curly brackets (`{ ... }`).  Also, if you assign these to lists (e.g. in a for loop), you need to use a list environment (`listenv`) instead of a plain list.
+
+However, as show below, there are few cases where you might run into some hurdles, but, as also shown, they are often easy to overcome.  These are often related to global variables.  
+
+_If you identify other cases, please consider [reporting](https://github.com/HenrikBengtsson/future/issues/) them so they can be documented here and possibly even be fixed._
+
+
+## Issues with globals
+
+
+### Missing or incorrect globals (false negatives)
+
+#### Global variable obscured by subassignment
+When a global variable is a vector, a matrix, a list, a data frame, an environment, or any other type of object that can be assigned via subsetting, the global package fails to identify it as a global variable if its first occurrence in the future expression is as part of a subsetting assignment.
+For example,
+```r
+> library("future")
+> plan(lazy)
+> x <- matrix(1:12, nrow=3, ncol=4)
+> y %<-% {
++   x[1,1] <- 3
++   42
++ }
+> rm(x)
+> y
+Error in x[1, 1] <- 3 : object 'x' not found
+```
+Another example is
+```r
+> library("future")
+> plan(lazy)
+> x <- list(a=1, b=2)
+> y %<-% {
++   x$c <- 3
++   42
++ }
+> rm(x)
+> y
+Error in x$c <- 3 : object 'x' not found
+```
+A workaround is to explicitly tell the future package about the global variable by simply listing it at the beginning of the expression, e.g.
+```r
+> library("future")
+> plan(lazy)
+> x <- list(a=1, b=2)
+> y %<-% {
++   x  ## Force 'x' to be global
++   x$c <- 3
++   42
++ }
+> rm(x)
+> y
+[1] 42
+```
+
+_Comment_: The goal is that the [globals] package will also handle the above case in a future version.  
+
+
+
+#### do.call() - function not found
+When calling a function using `do.call()` make sure to specify the function as the object itself and not by name.  This will help identify the function as a global object in the future expression.  For instance, use
+```r
+do.call(file_ext, list("foo.txt"))
+```
+instead of
+```r
+do.call("file_ext", list("foo.txt"))
+```
+so that `file_ext()` is properly located and exported.  Although you may not notice a difference when evaluating futures in the same R session, it may become a problem if you use a character string instead of a function object when futures are evaluated in external R sessions, such as on a cluster.
+It may also become a problem with lazy futures if the intended function is redefined after the future is resolved.  For example,
+```r
+> library("future")
+> library("listenv")
+> library("tools")
+> plan(lazy)
+> pathnames <- c("foo.txt", "bar.png", "yoo.md")
+> res <- listenv()
+> for (ii in seq_along(pathnames)) {
++   res[[ii]] %<-% do.call("file_ext", list(pathnames[ii]))
++ }
+> file_ext <- function(...) "haha!"
+> unlist(res)
+[1] "haha!" "haha!" "haha!"
+```
+
+<%---
+### False globals due to non-standard evaluation (false positives)
+
+#### subset(data, x < 3)
+
+Consider the following use of `subset()`:
+```r
+> data <- data.frame(x=1:5, y=1:5)
+> v <- subset(data, x < 3)$y
+> v
+[1] 1 2
+```
+From a static code inspection point of view, the expression `x < 3` asks for variable `x` to be compared to 3, and there is nothing specifying that `x` is part of `data` and not the global environment.  That `x` is indeed part of the `data` object can only safely be inferred at runtime when `subset()` is called.  This is not a problem in the above snippet, but when using futures all global/unknown variables need to be captured when the future is created (it is too late to do it when the  [...]
+```r
+> library("future")
+> data <- data.frame(x=1:5, y=1:5)
+> v %<-% subset(data, x < 3)$y
+Error in globalsOf(expr, envir = envir, tweak = tweakExpression, dotdotdot = "return",  :
+  Identified a global by static code inspection, but failed to locate the corresponding
+  object in the relevant environments: 'x'
+```
+Above, code inspection of the future expression `subset(data, x < 3)$y` incorrectly identifies `x` as a global variables that needs to be captured ("frozen") for the (lazy) future.  Since no such variable `x` exists, we get an error.
+
+A clearer and backward-compatible solution to this problem is to explicitly specify the context of `x`, i.e.
+```r
+> data <- data.frame(x=1:5, y=1:5)
+> v %<-% subset(data, data$x < 3)$y
+> v
+[1] 1 2
+```
+
+An alternative is to use a dummy variable.  In contrast to the code-inspection algorithm used to identify globals, _we know from reading the documentation_ that `subset()` will look for `x` in the `data` object, not in the parent environments.  Armed with this knowledge, we can trick the [future] package (more precisely the [globals] package) to pick up a dummy variable `x` instead, e.g.
+```r
+> data <- data.frame(x=1:5, y=1:5)
+> x <- NULL ## To please future et al.
+> v %<-% subset(data, x < 3)$y
+> v
+[1] 1 2
+```
+
+#### ggplot2
+Another common use case for non-standard evaluation is when creating ggplot2 figures.  For instance, in
+```r
+> library("ggplot2")
+> p <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
+> p
+```
+fields `mpg` and `wt` of the `mtcars` data object are plotted against each other.  That `mpg` and `wt` are fields of `mtcars` cannot be inferred from code inspection alone, but you need to know that that is how ggplot2 works.  Analogously to the above `subset()` example, this explains why we get the following error:
+```r
+> library("future")
+> library("ggplot2")
+> p %<-% { ggplot(mtcars, aes(wt, mpg)) + geom_point() }
+Error in globalsOf(expr, envir = envir, tweak = tweakExpression, dotdotdot = "return",  :
+  Identified a global by static code inspection, but failed to locate the corresponding
+  object in the relevant environments: 'wt'
+```
+A few comments are needed here.  First of all, because `%<-%` has higher precedence than `+`, we need to place all of the ggplot2 expression within curly brackets, otherwise, we get an error.  Second, the reason for only `wt` being listed as a missing global variable and not `mpg` is because the latter is (incorrectly) located to be `ggplot2::mpg`.
+
+One workaround is to make use of the `*_string()` functions of ggplot2, e.g.
+```r
+> p %<-% { ggplot(mtcars, aes_string('wt', 'mpg')) + geom_point() }
+> p
+```
+Another one, is to explicitly specify `mtcars$wt` and `mtcars$mpg`, which may become a bit tedious.
+A third alternative is to make use of dummy variables `wt` and `mpg`, i.e.
+```r
+> p %<-% {
++   wt <- mpg <- NULL
++   ggplot(mtcars, aes(wt, mpg)) + geom_point()
++ }
+> p
+```
+By the way, since all futures are evaluated in a local environment, the dummy variables are _not_ assigned to the calling environment.
+---%>
+
+
+## Trying to pass an unresolved future to another future
+It is not possible for a future to resolve another one unless it was created by the future trying to resolve it.  For instance, the following gives an error:
+```r
+> library("future")
+> plan(multiprocess)
+> f1 <- future({ Sys.getpid() })
+> f2 <- future({ value(f1) })
+> v1 <- value(f1)
+[1] 7464
+> v2 <- value(f2)
+Error: Invalid usage of futures: A future whose value has not yet been collected
+ can only be queried by the R process (cdd013cb-e045-f4a5-3977-9f064c31f188; pid
+ 1276 on MyMachine) that created it, not by any other R processes (5579f789-e7b6
+ -bace-c50d-6c7a23ddb5a3; pid 2352 on MyMachine): {; Sys.getpid(); }
+```
+This is because the main R process creates two futures, but then the second future tries to retrieve the value of the first one.  This is an invalid request because the second future has no channel to communicate with the first future; it is only the process that created a future who can communicate with it(*).
+
+Note that it is only _unresolved_ futures that cannot be queried this way.  Thus, the solution to the above problem is to make sure all futures are resolved before they are passed to other futures, e.g.
+```r
+> f1 <- future({ Sys.getpid() })
+> v1 <- value(f1)
+> v1
+[1] 7464
+> f2 <- future({ value(f1) })
+> v2 <- value(f2)
+> v2
+[1] 7464
+```
+This works because the value has already been collected and stored inside future `f1` before future `f2` is created.  Since the value is already stored internally, `value(f1)` is readily available everywhere.  Of course, instead of using `value(f1)` for the second future, it would be more readable and cleaner to simply use `v1`.
+
+The above is typically not a problem when future assignments are used.  For example:
+```r
+> v1 %<-% { Sys.getpid() })
+> v2 %<-% { v1 }
+> v1
+[1] 2352
+> v2
+[1] 2352
+```
+The reason that this approach works out of the box is because in the second future assignment `v1` is identified as a global variable, which is retrieved.  Up to this point, `v1` is a promise ("delayed assignment" in R), but when it is retrieved as a global variable its value is resolved and `v1` becomes a regular variable.
+
+However, there are cases where future assignments can be passed via global variables without being resolved.  This can happen if the future assignment is done to an element of an environment (including list environments).  For instance,
+```r
+> library("listenv")
+> x <- listenv()
+> x$a %<-% { Sys.getpid() }
+> x$b %<-% { x$a }
+> x$a
+[1] 2352
+> x$b
+Error: Invalid usage of futures: A future whose value has not yet been collected
+ can only be queried by the R process (cdd013cb-e045-f4a5-3977-9f064c31f188; pid
+ 1276 on localhost) that created it, not by any other R processes (2ce86ccd-5854
+ -7a05-1373-e1b20022e4d8; pid 7464 on localhost): {; Sys.getpid(); }
+```
+As previously, this can be avoided by making sure `x$a` is resolved first, which can be one in various ways, e.g. `dummy <- x$a`, `resolve(x$a)` and `force(x$a)`.
+
+_Footnote_: (*) Although certain types of futures, such as eager and lazy ones, could be passed on to other futures and be resolved there because they share the same evaluation process, by definition of the Future API it is invalid to do so regardless of future type.  This conservative approach is taken in order to make future expressions behave consistently regardless of the type of future used.
+
+
+## Miscellaneous
+
+### Clashes with other packages
+
+Sometimes other packages have functions or operators with the same name as the future package, and if those packages are attached _after_ the future package, their objects will mask the ones of the future package.  For instance, the igraph package also defines a `%<-%` operator which clashes with the one in future _if used at the prompt or in a script_ (it is not a problem inside package because there we explicitly import objects in a known order).  Here is what we might get:
+```r
+> library("future")
+> library("igraph")
+
+Attaching package: 'igraph'
+
+The following objects are masked from 'package:future':
+
+    %<-%, %->%
+
+The following objects are masked from 'package:stats':
+
+    decompose, spectrum
+
+The following object is masked from 'package:base':
+
+    union
+
+> y %<-% { 42 }
+Error in get(".igraph.from", parent.frame()) : 
+  object '.igraph.from' not found
+```
+Here we get an error because `%<-%` is from igraph and not the future assignment operator as we wanted.  This can be confirmed as:
+```r
+> environment(`%<-%`)
+<environment: namespace:igraph>
+```
+
+To avoid this problem, attach the two packages in opposite order such that future comes last and thereby overrides igraph, i.e.
+```r
+> library("igraph")
+> library("future")
+
+Attaching package: 'future'
+
+The following objects are masked from 'package:igraph':
+
+%<-%, %->%
+
+> y %<-% { 42 }
+> y
+[1] 42
+```
+
+An alternative is to detach the future package and re-attach it, which will achieve the same thing:
+```r
+> detach("package:future")
+> library("future")
+```
+
+Yet another alternative is to explicitly override the object by importing it to the global environment, e.g.
+```r
+> `%<-%` <- future::`%<-%`
+> y %<-% { 42 }
+> y
+[1] 42
+```
+In this case, it does not matter in what order the packages are attached because we will always use the copy of `` future::`%<-%` ``.
+
+
+
+### Syntax error: "non-numeric argument to binary operator"
+The future assignment operator `%<-%` is a _binary infix operator_, which means it has higher precedence than most other binary operators but also higher than some of the unary operators in R.  For instance, this explains why we get the following error:
+```r
+> x %<-% 2 * runif(1)
+Error in x %<-% 2 * runif(1) : non-numeric argument to binary operator
+```
+What effectively is happening here is that because of the higher priority of `%<-%`, we first create a future `x %<-% 2` and then we try to multiply the future (not its value) with the value of `runif(1)` - which makes no sense.  In order to properly assign the future variable, we need to put the future expression within curly brackets;
+```r
+> x %<-% { 2 * runif(1) }
+> x
+[1] 1.030209
+```
+Parentheses will also do.  For details on precedence on operators in R, see Section 'Infix and prefix operators' in the 'R Language Definition' document.
+
+
+
+[future]: https://cran.r-project.org/package=future
+[globals]: https://cran.r-project.org/package=globals
+[listenv]: https://cran.r-project.org/package=listenv
+
+---
+Copyright Henrik Bengtsson, 2015-2016
diff --git a/vignettes/future-3-topologies.md.rsp b/vignettes/future-3-topologies.md.rsp
new file mode 100644
index 0000000..7b1ba5c
--- /dev/null
+++ b/vignettes/future-3-topologies.md.rsp
@@ -0,0 +1,174 @@
+<%@meta language="R-vignette" content="--------------------------------
+%\VignetteIndexEntry{A Future for R: Future Topologies}
+%\VignetteAuthor{Henrik Bengtsson}
+%\VignetteKeyword{R}
+%\VignetteKeyword{package}
+%\VignetteKeyword{vignette}
+%\VignetteKeyword{future}
+%\VignetteKeyword{promise}
+%\VignetteEngine{R.rsp::rsp}
+%\VignetteTangle{FALSE}
+--------------------------------------------------------------------"%>
+<%
+library("R.utils")
+`%<-%` <- future::`%<-%`
+options("withCapture/newline"=FALSE)
+%>
+
+# <%@meta name="title"%>
+
+Futures can be nested in R such that one future creates another set of futures and so on.  This may, for instance, occur within nested for loops, e.g.
+```r
+library("future")
+library("listenv")
+x <- listenv()
+for (ii in 1:3) {
+  x[[ii]] %<-% {
+    y <- listenv()
+    for (jj in 1:3) {
+      y[[jj]] %<-% { ii + jj/10 }
+    }
+	y
+  }
+}
+unlist(x)
+## [1] 1.1 1.2 1.3 2.1 2.2 2.3 3.1 3.2 3.3
+```
+The default is to use eager futures unless otherwise specified, which is also true for nested futures.  If we for instance specify, `plan(multiprocess)`, the first layer of futures (`x[[ii]] %<-% { expr }`) will be processed asynchronously in background R processes, and the futures in the second layer of futures (`y[[jj]] %<-% { expr }`) will be processed synchronously in the current R processes (one of the background processes).  If we wish to use a different strategy for the second lay [...]
+
+
+## Example: High-Throughput Sequencing
+Consider a high-throughput sequencing (HT-Seq) project with 50 human DNA samples where we have one FASTQ file per sample containing the raw sequence reads as they come out of the sequencing machine.  With this data, we wish to align each FASTQ to a reference genome such that we generate 24 individual BAM files per sample - one per chromosome.
+
+Here is the layout of what such an analysis could look like in R using futures.
+```r
+library("future")
+library("listenv")
+htseq_align <- function(fq, chr) { chr }
+
+fqs <- dir(pattern="[.]fastq$")
+
+bams <- listenv()
+for (ss in seq_along(fqs)) {
+  fq <- fqs[ss]
+  bams[[ss]] %<-% {
+    bams_ss <- listenv()
+    for (cc in 1:24) {
+      bams_ss[[cc]] %<-% htseq_align(fq, chr=cc)
+    }
+    as.list(bams_ss)
+  }
+}
+bams <- as.list(bams)
+```
+
+The default is to use eager futures, so without further specifications, the above will process each sample and each chromosome sequentially.  Next, we will consider what can be done with the following two computer setups:
+
+* A single machine with 8 cores
+* A compute cluster with 3 machines each with 16 cores
+
+### One multi-core machine
+With a single machine of 8 cores, we could choose to process multiple samples at the same while processing chromosomes sequentially.  In other words, we would like to evaluate the outer layer of futures using multiprocess futures and the inner ones as regular (uniprocess) eager futures.  This can be specified as:
+```r
+plan(list(multiprocess, eager))
+```
+The internals for processing multiprocess future queries `availableCores()` to infer how many cores can be used simultaneously, so there is no need to explicitly specify that there are 8 cores available.
+
+_Comment_: Since eager is the default future, we could skip trailing eager futures in the setup, e.g. `plan(list(multiprocess))` or just `plan(multiprocess)`.  However, it does hurt to be explicit.
+
+If we instead would like to process the sample sequentially and the chromosomes in parallel, we can use:
+```r
+plan(list(eager, multiprocess))
+```
+
+We could also process the data such that we allocate two cores for processing two samples in parallel each using four cores for processing four chromosomes in parallel:
+```r
+plan(list(tweak(multiprocess, workers=2), tweak(multiprocess, workers=4)))
+```
+
+
+### An ad-hoc compute cluster
+With a compute cluster of 3 machines each with 16 cores, we can run up to 48 alignment processes in parallel.  A natural setup is to have one machine process one sample in parallel.  We could specify this as:
+```r
+nodes <- c("n1", "n2", "n3")
+plan(list(tweak(cluster, workers=nodes), multiprocess))
+```
+_Comment:_ Multiprocess futures are agile to its environment, that is, they will query the machine they are running on to find out how many parallel processes it can run at the same time.
+
+One possible downside to the above setup is that we might not utilize all available cores all the time.  This is because the alignment of the shorter chromosomes will finish sooner than the longer ones, which means that we might at the end of each sample have only a few alignment processes running on each machine leaving the remaining cores idle/unused.  An alternative set up is then to use the following setup:
+```r
+nodes <- rep(c("n1", "n2", "n3"), each=8)
+plan(list(tweak(cluster, workers=nodes), multiprocess))
+```
+This will cause up to 24 (=3*8) samples to be processed in parallel each processing two chromosomes at the same time.
+
+
+## Example: A remote compute cluster
+Imagine we have access to a remote compute cluster, with login node `remote.server.org`, and that the cluster has three nodes `n1`, `n2`, and `n3`.  Also, let us assume we have already set up the cluster such that we can log in via public key authentication via SSH, i.e. when we do `ssh remote.server.org` authentication is done automatically.
+
+With the above setup, we can use nested futures in our local R session to evaluate R expression on the remote compute cluster and its three nodes.  Here is a proof of concept illustrating how the different nested futures are evaluated on different machines.
+
+```r
+library("future")
+library("listenv")
+
+## Set up access to remote login node
+login <- tweak(remote, workers="remote.server.org")
+plan(login)
+
+## Set up cluster nodes on login node
+nodes %<-% { .keepme <- parallel::makeCluster(c("n1", "n2", "n3")) }
+
+## Specify future topology
+## login node -> { cluster nodes } -> { multiple cores }
+plan(list(
+  login,
+  tweak(cluster, workers=nodes),
+  multiprocess
+))
+
+
+## (a) This will be evaluated on the cluster login computer
+x %<-% {
+  thost <- Sys.info()[["nodename"]]
+  tpid <- Sys.getpid()
+  y <- listenv()
+  for (task in 1:4) {
+    ## (b) This will be evaluated on a compute node on the cluster
+    y[[task]] %<-% {
+      mhost <- Sys.info()[["nodename"]]
+      mpid <- Sys.getpid()
+      z <- listenv()
+      for (jj in 1:2) {
+        ## (c) These will be evaluated in separate processes on the same compute node
+        z[[jj]] %<-% data.frame(task=task, top.host=thost, top.pid=tpid,
+                                mid.host=mhost, mid.pid=mpid,
+                                host=Sys.info()[["nodename"]], pid=Sys.getpid())
+      }
+      Reduce(rbind, z)
+    }
+  }
+  Reduce(rbind, y)
+}
+
+print(x)
+##   task top.host top.pid mid.host mid.pid host    pid
+## 1    1    login  391547       n1  391878   n1 393943
+## 2    1    login  391547       n1  391878   n1 393951
+## 3    2    login  391547       n2  392204   n2 393971
+## 4    2    login  391547       n2  392204   n2 393978
+## 5    3    login  391547       n3  392527   n3 394040
+## 6    3    login  391547       n3  392527   n3 394048
+## 7    4    login  391547       n1  391878   n1 393959
+## 8    4    login  391547       n1  391878   n1 393966
+```
+
+Try the above `x %<-% { ... }` future with, say, `plan(list(lazy, multiprocess))` or `plan(list(eager, lazy, multiprocess))` and see what the output will be.
+
+
+[listenv]: http://cran.r-project.org/package=listenv
+[globals]: http://cran.r-project.org/package=globals
+[Futures in R: Common issues with solutions]: future-issues.html
+
+---
+Copyright Henrik Bengtsson, 2015-2016

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/r-cran-future.git



More information about the debian-med-commit mailing list