foundationdb/flow.html

440 lines
41 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>Flow &#8212; FoundationDB ON documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/bootstrap-sphinx.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/_sphinx_javascript_frameworks_compat.js"></script>
<script src="_static/doctools.js"></script>
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Simulation and Testing" href="testing.html" />
<link rel="prev" title="Fault Tolerance" href="fault-tolerance.html" />
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge,chrome=1'>
<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1'>
<meta name="apple-mobile-web-app-capable" content="yes">
<script type="text/javascript" src="_static/js/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="_static/js/jquery-fix.js"></script>
<script type="text/javascript" src="_static/bootstrap-3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript" src="_static/bootstrap-sphinx.js"></script>
</head><body>
<div id="navbar" class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<!-- .btn-navbar is used as the toggle for collapsed navbar content -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="index.html">
FoundationDB</a>
<span class="navbar-text navbar-version pull-left"><b>7.3.57</b></span>
</div>
<div class="collapse navbar-collapse nav-collapse">
<ul class="nav navbar-nav">
<li><a href="contents.html">Site Map</a></li>
<li class="dropdown globaltoc-container">
<a role="button"
id="dLabelGlobalToc"
data-toggle="dropdown"
data-target="#"
href="index.html">Site <b class="caret"></b></a>
<ul class="dropdown-menu globaltoc"
role="menu"
aria-labelledby="dLabelGlobalToc"><ul class="current">
<li class="toctree-l1"><a class="reference internal" href="local-dev.html">Local Development</a></li>
<li class="toctree-l1"><a class="reference internal" href="internal-dev-tools.html">Internal Dev Tools</a></li>
<li class="toctree-l1"><a class="reference internal" href="why-foundationdb.html">Why FoundationDB</a><ul>
<li class="toctree-l2"><a class="reference internal" href="transaction-manifesto.html">Transaction Manifesto</a></li>
<li class="toctree-l2"><a class="reference internal" href="cap-theorem.html">CAP Theorem</a></li>
<li class="toctree-l2"><a class="reference internal" href="consistency.html">Consistency</a></li>
<li class="toctree-l2"><a class="reference internal" href="scalability.html">Scalability</a></li>
</ul>
</li>
<li class="toctree-l1 current"><a class="reference internal" href="technical-overview.html">Technical Overview</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="architecture.html">Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="performance.html">Performance</a></li>
<li class="toctree-l2"><a class="reference internal" href="benchmarking.html">Benchmarking</a></li>
<li class="toctree-l2"><a class="reference internal" href="engineering.html">Engineering</a></li>
<li class="toctree-l2"><a class="reference internal" href="features.html">Features</a></li>
<li class="toctree-l2"><a class="reference internal" href="layer-concept.html">Layer Concept</a></li>
<li class="toctree-l2"><a class="reference internal" href="anti-features.html">Anti-Features</a></li>
<li class="toctree-l2"><a class="reference internal" href="experimental-features.html">Experimental-Features</a></li>
<li class="toctree-l2"><a class="reference internal" href="transaction-processing.html">Transaction Processing</a></li>
<li class="toctree-l2"><a class="reference internal" href="fault-tolerance.html">Fault Tolerance</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Flow</a></li>
<li class="toctree-l2"><a class="reference internal" href="testing.html">Simulation and Testing</a></li>
<li class="toctree-l2"><a class="reference internal" href="kv-architecture.html">FoundationDB Architecture</a></li>
<li class="toctree-l2"><a class="reference internal" href="read-write-path.html">FDB Read and Write Path</a></li>
<li class="toctree-l2"><a class="reference internal" href="ha-write-path.html">FDB HA Write Path: How a mutation travels in FDB HA</a></li>
<li class="toctree-l2"><a class="reference internal" href="consistency-check-urgent.html">Consistency Checker Urgent</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="client-design.html">Client Design</a><ul>
<li class="toctree-l2"><a class="reference internal" href="getting-started-mac.html">Getting Started on macOS</a></li>
<li class="toctree-l2"><a class="reference internal" href="getting-started-linux.html">Getting Started on Linux</a></li>
<li class="toctree-l2"><a class="reference internal" href="downloads.html">Downloads</a></li>
<li class="toctree-l2"><a class="reference internal" href="developer-guide.html">Developer Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="data-modeling.html">Data Modeling</a></li>
<li class="toctree-l2"><a class="reference internal" href="client-testing.html">Client Testing</a></li>
<li class="toctree-l2"><a class="reference internal" href="client-testing.html#testing-error-handling-with-buggify">Testing Error Handling with Buggify</a></li>
<li class="toctree-l2"><a class="reference internal" href="client-testing.html#simulation-and-cluster-workloads">Simulation and Cluster Workloads</a></li>
<li class="toctree-l2"><a class="reference internal" href="client-testing.html#api-tester">API Tester</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-general.html">Using FoundationDB Clients</a></li>
<li class="toctree-l2"><a class="reference internal" href="transaction-tagging.html">Transaction Tagging</a></li>
<li class="toctree-l2"><a class="reference internal" href="known-limitations.html">Known Limitations</a></li>
<li class="toctree-l2"><a class="reference internal" href="transaction-profiler-analyzer.html">Transaction profiling and analyzing</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-version-upgrade-guide.html">API Version Upgrade Guide</a></li>
<li class="toctree-l2"><a class="reference internal" href="tenants.html">Tenants</a></li>
<li class="toctree-l2"><a class="reference internal" href="automatic-idempotency.html">Automatic Idempotency</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="design-recipes.html">Design Recipes</a><ul>
<li class="toctree-l2"><a class="reference internal" href="blob.html">Blob</a></li>
<li class="toctree-l2"><a class="reference internal" href="blob-java.html">Blob</a></li>
<li class="toctree-l2"><a class="reference internal" href="hierarchical-documents.html">Hierarchical Documents</a></li>
<li class="toctree-l2"><a class="reference internal" href="hierarchical-documents-java.html">Hierarchical Documents</a></li>
<li class="toctree-l2"><a class="reference internal" href="multimaps.html">Multimaps</a></li>
<li class="toctree-l2"><a class="reference internal" href="multimaps-java.html">Multimaps</a></li>
<li class="toctree-l2"><a class="reference internal" href="priority-queues.html">Priority Queues</a></li>
<li class="toctree-l2"><a class="reference internal" href="priority-queues-java.html">Priority Queues</a></li>
<li class="toctree-l2"><a class="reference internal" href="queues.html">Queues</a></li>
<li class="toctree-l2"><a class="reference internal" href="queues-java.html">Queues</a></li>
<li class="toctree-l2"><a class="reference internal" href="segmented-range-reads.html">Segmented Range Reads</a></li>
<li class="toctree-l2"><a class="reference internal" href="segmented-range-reads-java.html">Segmented Range Reads</a></li>
<li class="toctree-l2"><a class="reference internal" href="simple-indexes.html">Simple Indexes</a></li>
<li class="toctree-l2"><a class="reference internal" href="simple-indexes-java.html">Simple Indexes</a></li>
<li class="toctree-l2"><a class="reference internal" href="spatial-indexing.html">Spatial Indexing</a></li>
<li class="toctree-l2"><a class="reference internal" href="spatial-indexing-java.html">Spatial Indexing</a></li>
<li class="toctree-l2"><a class="reference internal" href="subspace-indirection.html">Subspace Indirection</a></li>
<li class="toctree-l2"><a class="reference internal" href="subspace-indirection-java.html">Subspace Indirection</a></li>
<li class="toctree-l2"><a class="reference internal" href="tables.html">Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="tables-java.html">Tables</a></li>
<li class="toctree-l2"><a class="reference internal" href="vector.html">Vector</a></li>
<li class="toctree-l2"><a class="reference internal" href="vector-java.html">Vector</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="api-reference.html">API Reference</a><ul>
<li class="toctree-l2"><a class="reference internal" href="api-python.html">Python API</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-ruby.html">Ruby API</a></li>
<li class="toctree-l2"><a class="reference external" href="relative://javadoc/index.html">Java API</a></li>
<li class="toctree-l2"><a class="reference external" href="https://godoc.org/github.com/apple/foundationdb/bindings/go/src/fdb">Go API</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-c.html">C API</a></li>
<li class="toctree-l2"><a class="reference internal" href="api-error-codes.html">Error Codes</a></li>
<li class="toctree-l2"><a class="reference internal" href="special-keys.html">Special Keys</a></li>
<li class="toctree-l2"><a class="reference internal" href="global-configuration.html">Global Configuration</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="tutorials.html">Tutorials</a><ul>
<li class="toctree-l2"><a class="reference internal" href="class-scheduling.html">Class Scheduling</a></li>
<li class="toctree-l2"><a class="reference internal" href="largeval.html">Managing Large Values and Blobs</a></li>
<li class="toctree-l2"><a class="reference internal" href="time-series.html">Time-Series Data</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="administration.html">Administration</a><ul>
<li class="toctree-l2"><a class="reference internal" href="configuration.html">Configuration</a></li>
<li class="toctree-l2"><a class="reference internal" href="moving-a-cluster.html">Moving a Cluster to New Machines</a></li>
<li class="toctree-l2"><a class="reference internal" href="tls.html">Transport Layer Security</a></li>
<li class="toctree-l2"><a class="reference internal" href="authorization.html">Authorization</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="monitored-metrics.html"><strong>Monitored Metrics</strong></a></li>
<li class="toctree-l1"><a class="reference internal" href="redwood.html">Redwood Storage Engine</a></li>
<li class="toctree-l1"><a class="reference internal" href="visibility.html">Visibility Documents</a><ul>
<li class="toctree-l2"><a class="reference internal" href="request-tracing.html">Request Tracing</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="earlier-release-notes.html">Earlier Release Notes</a><ul>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-014.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-016.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-021.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-022.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-023.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-100.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-200.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-300.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-400.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-410.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-420.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-430.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-440.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-450.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-460.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-500.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-510.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-520.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-600.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-610.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-620.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-630.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-700.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-710.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-720.html">Release Notes</a></li>
<li class="toctree-l2"><a class="reference internal" href="release-notes/release-notes-730.html">Release Notes</a></li>
</ul>
</li>
</ul>
</ul>
</li>
<li class="dropdown">
<a role="button"
id="dLabelLocalToc"
data-toggle="dropdown"
data-target="#"
href="#">Page <b class="caret"></b></a>
<ul class="dropdown-menu localtoc"
role="menu"
aria-labelledby="dLabelLocalToc"><ul>
<li><a class="reference internal" href="#">Flow</a><ul>
<li><a class="reference internal" href="#engineering-challenges">Engineering challenges</a></li>
<li><a class="reference internal" href="#a-first-look">A first look</a></li>
<li><a class="reference internal" href="#flow-features">Flow features</a><ul>
<li><a class="reference internal" href="#promise-t-and-future-t">Promise&lt;T&gt; and Future&lt;T&gt;</a></li>
<li><a class="reference internal" href="#wait">wait()</a></li>
<li><a class="reference internal" href="#actor">ACTOR</a></li>
<li><a class="reference internal" href="#state">State</a></li>
<li><a class="reference internal" href="#promisestream-t-futurestream-t">PromiseStream&lt;T&gt;, FutureStream&lt;T&gt;</a></li>
<li><a class="reference internal" href="#waitnext">waitNext()</a></li>
<li><a class="reference internal" href="#choose-when">choose … when</a></li>
<li><a class="reference internal" href="#example-a-server-interface">Example: A Server Interface</a></li>
</ul>
</li>
<li><a class="reference internal" href="#caveats">Caveats</a></li>
</ul>
</li>
</ul>
</ul>
</li>
<li>
<a href="fault-tolerance.html" title="Previous Chapter: Fault Tolerance"><span class="glyphicon glyphicon-chevron-left visible-sm"></span><span class="hidden-sm hidden-tablet">&laquo; Fault Tolerance</span>
</a>
</li>
<li>
<a href="testing.html" title="Next Chapter: Simulation and Testing"><span class="glyphicon glyphicon-chevron-right visible-sm"></span><span class="hidden-sm hidden-tablet">Simulation an... &raquo;</span>
</a>
</li>
</ul>
<form class="navbar-form navbar-right" action="search.html" method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search" />
</div>
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-3">
<div id="sidebar" class="bs-sidenav" role="complementary"><ul>
<li><a class="reference internal" href="#">Flow</a><ul>
<li><a class="reference internal" href="#engineering-challenges">Engineering challenges</a></li>
<li><a class="reference internal" href="#a-first-look">A first look</a></li>
<li><a class="reference internal" href="#flow-features">Flow features</a><ul>
<li><a class="reference internal" href="#promise-t-and-future-t">Promise&lt;T&gt; and Future&lt;T&gt;</a></li>
<li><a class="reference internal" href="#wait">wait()</a></li>
<li><a class="reference internal" href="#actor">ACTOR</a></li>
<li><a class="reference internal" href="#state">State</a></li>
<li><a class="reference internal" href="#promisestream-t-futurestream-t">PromiseStream&lt;T&gt;, FutureStream&lt;T&gt;</a></li>
<li><a class="reference internal" href="#waitnext">waitNext()</a></li>
<li><a class="reference internal" href="#choose-when">choose … when</a></li>
<li><a class="reference internal" href="#example-a-server-interface">Example: A Server Interface</a></li>
</ul>
</li>
<li><a class="reference internal" href="#caveats">Caveats</a></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="body col-md-9 content" role="main">
<section id="flow">
<h1>Flow</h1>
<section id="engineering-challenges">
<h2>Engineering challenges</h2>
<p>FoundationDB began with ambitious goals for both <a class="reference internal" href="performance.html"><span class="doc">high performance</span></a> per node and <a class="reference internal" href="scalability.html"><span class="doc">scalability</span></a>. We knew that to achieve these goals we would face serious engineering challenges while developing the FoundationDB core. Wed need to implement efficient asynchronous communicating processes of the sort supported by <a class="reference external" href="http://en.wikipedia.org/wiki/Erlang_(programming_language)">Erlang</a> or the <a class="reference external" href="http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx">Async library in .NET</a>, but wed also need the raw speed and I/O efficiency of C++. Finally, wed need to perform extensive simulation to engineer for reliability and fault tolerance on large clusters.</p>
<p>To meet these challenges, we developed several new tools, the first of which is Flow, a new programming language that brings <a class="reference external" href="http://en.wikipedia.org/wiki/Actor_model">actor-based concurrency</a> to C++11. To add this capability, Flow introduces a number of new keywords and control-flow primitives for managing concurrency. Flow is implemented as a compiler which analyzes an asynchronous function (actor) and rewrites it as an object with many different sub-functions that use callbacks to avoid blocking (see <a class="reference external" href="https://github.com/Sage/streamlinejs">streamlinejs</a> for a similar concept using JavaScript). The Flow compilers output is normal C++11 code, which is then compiled to a binary using traditional tools. Flow also provides input to our simulation tool, which conducts deterministic simulations of the entire system, including its physical interfaces and failure modes. In short, Flow allows efficient concurrency within C++ in a maintainable and extensible manner, achieving all three major engineering goals:</p>
<ul class="simple">
<li><p>high performance (by compiling to native code),</p></li>
<li><p>actor-based concurrency (for high productivity development),</p></li>
<li><p>simulation support (for testing).</p></li>
</ul>
</section>
<section id="a-first-look">
<h2>A first look</h2>
<p>Actors in Flow receive asynchronous messages from each other using a data type called a <em>future</em>. When an actor requires a data value to continue computation, it waits for it without blocking other actors. The following simple actor performs asynchronous addition. It takes a future integer and a normal integer as an offset, waits on the future integer, and returns the sum of the value and the offset:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">ACTOR</span><span class="w"> </span><span class="n">Future</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">asyncAdd</span><span class="p">(</span><span class="n">Future</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">offset</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">wait</span><span class="p">(</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">offset</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="flow-features">
<h2>Flow features</h2>
<p>Flows new keywords and control-flow primitives support the capability to pass messages asynchronously between components. Heres a brief overview.</p>
<section id="promise-t-and-future-t">
<h3>Promise&lt;T&gt; and Future&lt;T&gt;</h3>
<p>The data types that connect asynchronous senders and receivers are <code class="docutils literal notranslate"><span class="pre">Promise&lt;T&gt;</span></code> and <code class="docutils literal notranslate"><span class="pre">Future&lt;T&gt;</span></code> for some C++ type <code class="docutils literal notranslate"><span class="pre">T</span></code>. When a sender holds a <code class="docutils literal notranslate"><span class="pre">Promise&lt;T&gt;</span></code>, it represents a promise to deliver a value of type <code class="docutils literal notranslate"><span class="pre">T</span></code> at some point in the future to the holder of the <code class="docutils literal notranslate"><span class="pre">Future&lt;T&gt;</span></code>. Conversely, a receiver holding a <code class="docutils literal notranslate"><span class="pre">Future&lt;T&gt;</span></code> can asynchronously continue computation until the point at which it actually needs the <code class="docutils literal notranslate"><span class="pre">T.</span></code></p>
<p>Promises and futures can be used within a single process, but their real strength in a distributed system is that they can traverse the network. For example, one computer could create a promise/future pair, then send the promise to another computer over the network. The promise and future will still be connected, and when the promise is fulfilled by the remote computer, the original holder of the future will see the value appear.</p>
</section>
<section id="wait">
<h3>wait()</h3>
<p>At the point when a receiver holding a <code class="docutils literal notranslate"><span class="pre">Future&lt;T&gt;</span></code> needs the <code class="docutils literal notranslate"><span class="pre">T</span></code> to continue computation, it invokes the <code class="docutils literal notranslate"><span class="pre">wait()</span></code> statement with the <code class="docutils literal notranslate"><span class="pre">Future&lt;T&gt;</span></code> as its parameter. The <code class="docutils literal notranslate"><span class="pre">wait()</span></code> statement allows the calling actor to pause execution until the value of the future is set, returning a value of type <code class="docutils literal notranslate"><span class="pre">T</span></code>. During the wait, other actors can continue execution, providing asynchronous concurrency within a single process.</p>
</section>
<section id="actor">
<h3>ACTOR</h3>
<p>Only functions labeled with the <code class="docutils literal notranslate"><span class="pre">ACTOR</span></code> tag can call <code class="docutils literal notranslate"><span class="pre">wait()</span></code>. Actors are the essential unit of asynchronous work and can be composed to create complex message-passing systems. By composing actors, futures can be chained together so that the result of one depends on the output of another.</p>
<p>An actor is declared as returning a <code class="docutils literal notranslate"><span class="pre">Future&lt;T&gt;</span></code> where <code class="docutils literal notranslate"><span class="pre">T</span></code> may be <code class="docutils literal notranslate"><span class="pre">Void</span></code> if the actors return value is used only for signaling. Each actor is preprocessed into a C++11 class with internal callbacks and supporting functions.</p>
</section>
<section id="state">
<h3>State</h3>
<p>The <code class="docutils literal notranslate"><span class="pre">state</span></code> keyword is used to scope a variable so that it is visible across multiple <code class="docutils literal notranslate"><span class="pre">wait()</span></code> statements within an actor. The use of a <code class="docutils literal notranslate"><span class="pre">state</span></code> variable is illustrated in the example actor below.</p>
</section>
<section id="promisestream-t-futurestream-t">
<h3>PromiseStream&lt;T&gt;, FutureStream&lt;T&gt;</h3>
<p>When a component wants to work with a <em>stream</em> of asynchronous messages rather than a single message, it can use <code class="docutils literal notranslate"><span class="pre">PromiseStream&lt;T&gt;</span></code> and <code class="docutils literal notranslate"><span class="pre">FutureStream&lt;T&gt;</span></code>. These constructs allow for two important features: multiplexing and reliable delivery of messages. They also play an important role in Flow design patterns. For example, many of the servers in FoundationDB expose their interfaces as a <code class="docutils literal notranslate"><span class="pre">struct</span></code> of promise streams—one for each request type.</p>
</section>
<section id="waitnext">
<h3>waitNext()</h3>
<p><code class="docutils literal notranslate"><span class="pre">waitNext()</span></code> is the counterpart of <code class="docutils literal notranslate"><span class="pre">wait()</span></code> for streams. It pauses program execution and waits for the next value in a <code class="docutils literal notranslate"><span class="pre">FutureStream</span></code>. If there is a value ready in the stream, execution continues without delay.</p>
</section>
<section id="choose-when">
<h3>choose … when</h3>
<p>The <code class="docutils literal notranslate"><span class="pre">choose</span></code> and <code class="docutils literal notranslate"><span class="pre">when</span></code> constructs allow an actor to wait for multiple futures at once in a ordered and predictable way.</p>
</section>
<section id="example-a-server-interface">
<h3>Example: A Server Interface</h3>
<p>Below is a actor that runs on single server communicating over the network. Its functionality is to maintain a count in response to asynchronous messages from other actors. It supports an interface implemented with a loop containing a <code class="docutils literal notranslate"><span class="pre">choose</span></code> statement with a <code class="docutils literal notranslate"><span class="pre">when</span></code> for each request type. Each <code class="docutils literal notranslate"><span class="pre">when</span></code> uses <code class="docutils literal notranslate"><span class="pre">waitNext()</span></code> to asynchronously wait for the next request in the stream. The add and subtract interfaces modify the count itself, stored with a state variable. The get interface takes a <code class="docutils literal notranslate"><span class="pre">Promise&lt;int&gt;</span></code> instead of just an <code class="docutils literal notranslate"><span class="pre">int</span></code> to facilitate sending back the return message.</p>
<p>To write the equivalent code directly in C++, a developer would have to implement a complex set of callbacks with exception-handling, requiring far more engineering effort. Flow makes it much easier to implement this sort of asynchronous coordination, with no loss of performance:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">ACTOR</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">serveCountingServerInterface</span><span class="p">(</span>
<span class="w"> </span><span class="n">CountingServerInterface</span><span class="w"> </span><span class="n">csi</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">state</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">choose</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">waitNext</span><span class="p">(</span><span class="n">csi</span><span class="p">.</span><span class="n">addCount</span><span class="p">.</span><span class="n">getFuture</span><span class="p">())){</span>
<span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">waitNext</span><span class="p">(</span><span class="n">csi</span><span class="p">.</span><span class="n">subtractCount</span><span class="p">.</span><span class="n">getFuture</span><span class="p">())){</span>
<span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">when</span><span class="w"> </span><span class="p">(</span><span class="n">Promise</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">waitNext</span><span class="p">(</span><span class="n">csi</span><span class="p">.</span><span class="n">getCount</span><span class="p">.</span><span class="n">getFuture</span><span class="p">())){</span>
<span class="w"> </span><span class="n">r</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="w"> </span><span class="n">count</span><span class="w"> </span><span class="p">);</span><span class="w"> </span><span class="c1">// goes to client</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
</section>
<section id="caveats">
<h2>Caveats</h2>
<p>Even though Flow code looks a lot like C++, it is not. It has different rules and the files are preprocessed. It is always important to keep this in mind when programming flow.</p>
<p>We still want to be able to use IDEs and modern editors (with language servers like cquery or clang-based completion engines like ycm). Because of this there is a header-file <code class="docutils literal notranslate"><span class="pre">actorcompiler.h</span></code> in flow which defines preprocessor definitions to make flow compile as normal C++ code. CMake even supports a special mode so that it doesnt preprocess flow files. This mode can be used by passing <code class="docutils literal notranslate"><span class="pre">-DOPEN_FOR_IDE=ON</span></code> to cmake. Additionally we generate a special <code class="docutils literal notranslate"><span class="pre">compile_commands.json</span></code> into the source-directory which will support opening the project in IDEs and editors that look for a compilation database.</p>
<p>Some preprocessor definitions will not fix all issues though. When programming Flow the following things have to be taken care of by the programmer:</p>
<ul>
<li><p>Local variables dont survive a call to <code class="docutils literal notranslate"><span class="pre">wait</span></code>. So this would be legal Flow code, but NOT legal C++ code:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">ACTOR</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="n">wait</span><span class="p">(</span><span class="n">someFuture</span><span class="p">);</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="w"> </span><span class="n">wait</span><span class="p">(</span><span class="n">someOtherFuture</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>
</div>
<p>In order to make this not break IDE-support one can either rename the second occurrence of this variable or, if this is not desired as it might make the code unreadable, one can use scoping:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">ACTOR</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w"> </span><span class="n">wait</span><span class="p">(</span><span class="n">someFuture</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="w"> </span><span class="n">wait</span><span class="p">(</span><span class="n">someOtherFuture</span><span class="p">)</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
</li>
<li><p>An <code class="docutils literal notranslate"><span class="pre">ACTOR</span></code> is compiled into a class internally. Which means that within an actor-function, <code class="docutils literal notranslate"><span class="pre">this</span></code> is a valid pointer to this class. But using them explicitly (or as described later implicitly) will break IDE support. One can use <code class="docutils literal notranslate"><span class="pre">THIS</span></code> and <code class="docutils literal notranslate"><span class="pre">THIS_ADDR</span></code> instead. But be careful as <code class="docutils literal notranslate"><span class="pre">THIS</span></code> will be of type <code class="docutils literal notranslate"><span class="pre">nullptr_t</span></code> in IDE-mode and of the actor-type in normal compilation mode.</p></li>
<li><p>Lambdas and state variables are weird in a sense. After actor compilation, a state variable is a member of the compiled actor class. In IDE mode it is considered a normal local variable. This can result in some surprising side-effects. So the following code will only compile if the method <code class="docutils literal notranslate"><span class="pre">Foo::bar</span></code> is defined as <code class="docutils literal notranslate"><span class="pre">const</span></code>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">ACTOR</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">state</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="n">f</span><span class="p">;</span>
<span class="w"> </span><span class="n">foo</span><span class="p">([</span><span class="o">=</span><span class="p">]()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">f</span><span class="p">.</span><span class="n">bar</span><span class="p">();</span><span class="w"> </span><span class="p">})</span>
<span class="p">}</span>
</pre></div>
</div>
<p>If it is not, one has to pass the member explicitly as a reference:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">ACTOR</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">state</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="n">f</span><span class="p">;</span>
<span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">f</span><span class="p">;</span>
<span class="w"> </span><span class="n">foo</span><span class="p">([</span><span class="n">x</span><span class="p">]()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span><span class="o">-&gt;</span><span class="n">bar</span><span class="p">();</span><span class="w"> </span><span class="p">})</span>
<span class="p">}</span>
</pre></div>
</div>
</li>
<li><p>state variables in Flow dont follow the normal scoping rules. So in Flow a state variable can be defined in an inner scope and later it can be used in the outer scope. In order to not break compilation in IDE-mode, always define state variables in the outermost scope they will be used.</p></li>
</ul>
</section>
</section>
</div>
</div>
</div>
<footer class="footer">
<div class="container">
<p class="pull-right">
<a href="#">Back to top</a>
<br/>
<div id="sourcelink">
<a href="_sources/flow.rst.txt"
rel="nofollow">Source</a>
</div>
</p>
<p>
&copy; Copyright 2013-2022 Apple, Inc and the FoundationDB project authors.<br/>
Last updated on Nov 20, 2024.<br/>
</p>
</div>
</footer>
</body>
</html>