<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Caffeinated Bitstream</title>
    <link>https://cafbit.com/</link>
    <description>Bits, bytes, and words.</description>
    <language>en-us</language>
    <managingEditor>noreply@cafbit.com (David Simmons)</managingEditor>
    <copyright>(C) 2026</copyright>
    <lastBuildDate>Sat, 28 Mar 2026 10:20:43 -0600</lastBuildDate>

    
        <item>
          <title>A game of zones: A cartographic exploration of Colorado&#39;s strangest city limits</title>
          <link>https://cafbit.com/post/game_of_zones/</link>
          <pubDate>Sat, 28 Mar 2026 10:20:43 -0600</pubDate>
          <guid>https://cafbit.com/post/game_of_zones/</guid>
          <description>&lt;div class=&#34;photo&#34;&gt;
  &lt;a href=&#34;https://cafbit.com/resource/game_of_zones/rand_mcnally_denver_1996.webp&#34;&gt;
    &lt;img src=&#34;https://cafbit.com/resource/game_of_zones/rand_mcnally_denver_1996.webp&#34; alt=&#34;Part of a 1996 Rand McNally map of the Denver area with municipalities shaded in different colors&#34; /&gt;
  &lt;/a&gt;
  &lt;p&gt;
    Part of a 1996 Rand McNally map of the Denver area, showing how different
    municipalities were shaded in different colors.
  &lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
  One thing I always appreciated about the old Rand McNally street maps was how
  each municipality was shaded in a different color with clear boundaries,
  making it easy to see where one stopped and another began. This allowed
  readers to know at a glance where city limits were, and understand which
  areas were incorporated into which cities, and which areas were
  unincorporated.
  The lack of municipality boundaries is one thing I miss about most modern
  digital maps.&lt;sup&gt;&lt;a href=&#34;#goz-footnote-1&#34;&gt;[1]&lt;/a&gt;&lt;/sup&gt; I understand
  municipal boundaries are of little practical value for most people&#39;s daily
  lives.&lt;sup&gt;&lt;a href=&#34;#goz-footnote-2&#34;&gt;[2]&lt;/a&gt;&lt;/sup&gt; Nonetheless, I think there
  are stories to be told by this data.
&lt;/p&gt;

&lt;p&gt;
  The area between Denver and Fort Collins is rapidly growing, with many
  formerly small towns booming and expanding their city limits in surprising
  ways. Likewise, many established suburbs are extending to areas far away from
  their traditional cores. The more I travel around this area, the more
  astonished I am by how some areas seem to be part of suburbs and towns that I
  never would have expected. I often find myself wishing for a map that clearly
  shows municipal boundaries so I can get a better idea of what is going on.
&lt;/p&gt;





&lt;h2&gt;The municipal boundary map&lt;/h2&gt;

&lt;p&gt;
  Not wanting to wait for someone else to make such a map, I downloaded the
  &lt;a href=&#34;https://download.geofabrik.de/north-america/us/colorado.html&#34;&gt;
  Colorado OpenStreetMap data&lt;/a&gt; and proceeded to make some software to
  generate exactly the sort of map I&#39;d like to see. The OpenStreetMap data set
  I used is from March 1, 2026. The contained boundary data is not very
  up-to-date &amp;mdash; when I browse the various municipal GIS systems, I notice that
  many of these municipalities now have additional territory. So we&#39;re probably
  looking at boundaries that are a few years old. However, in spite of not
  being a current snapshot of boundaries in 2026, this data should be good
  enough to get an idea of what&#39;s happening.
&lt;/p&gt;

&lt;div class=&#34;figure&#34;&gt;
  &lt;a href=&#34;https://cafbit.com/resource/game_of_zones/north-front-range.webp&#34;&gt;
    &lt;!-- Just inline the full size image so it looks okay on Retina displays. --&gt;
    &lt;!--
    &lt;img src=&#34;https://cafbit.com/resource/game_of_zones/north-front-range-thumb.webp&#34; /&gt;
    --&gt;
    &lt;img src=&#34;https://cafbit.com/resource/game_of_zones/north-front-range.webp&#34; alt=&#34;Map of municipal boundaries from Denver to Fort Collins&#34; /&gt;

  &lt;/a&gt;
  &lt;p&gt;
    A rendering of municipal boundaries from Denver to Fort Collins based on
    data provided by
    &lt;a href=&#34;https://www.openstreetmap.org/copyright&#34;&gt;OpenStreetMap&lt;/a&gt;.
    &lt;!--
    Click the map to view a larger, more legible version.
    --&gt;
  &lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
  I was not disappointed in the results. This map tells a lot of fascinating
  stories!
&lt;/p&gt;

&lt;h2&gt;Opportunistic annexation for fun and profit&lt;/h2&gt;

&lt;p&gt;
  Before diving into the map details, let&#39;s take a moment to understand how
  municipal annexation works in Colorado.
&lt;/p&gt;

&lt;!-- annexation incentives --&gt;

&lt;p&gt;
  Incentives rule the world. Municipalities are highly incentivized to annex
  areas that will bring them the most tax revenue (e.g. present or future
  commercial/retail areas with high sales tax potential, especially near major
  highways) and avoid annexing areas that may bring unwanted expenses (e.g.
  residential areas where they may be obligated to provide municipal services).
  Left to their own devices, they would selectively annex only the juiciest
  parcels they could find, even if many miles away.&lt;sup&gt;&lt;a href=&#34;#goz-footnote-3&#34;&gt;[3]&lt;/a&gt;&lt;/sup&gt;
&lt;/p&gt;

&lt;!-- colorado rules --&gt;

&lt;p&gt;
  Given the potential for abuse, states impose rules such as contiguity
  requirements on municipalities intended to curb such opportunistic
  annexations. In turn, municipalities attempt to find loopholes around the
  rules by engaging in practices such as
  &lt;a href=&#34;https://en.wikipedia.org/wiki/Municipal_annexation_in_the_United_States#Shoestring_annexation&#34;&gt;
  flagpole annexation&lt;/a&gt;
  &amp;mdash; annexing narrow parcels of land, often just the width of a highway,
  in order to annex distant parcels while being technically contiguous.
&lt;/p&gt;
&lt;p&gt;
  Colorado&#39;s annexation laws are based on the Municipal Annexation Act of 1965
  (C.R.S. § 31-12-101, et seq.) which has been amended many times over the years. For
  the purposes of interpreting the map, the key requirements are:
&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;b&gt;The one-sixth contiguity rule (§31-12-104(1)(a)).&lt;/b&gt; An annexation must
    have at least one-sixth of its perimeter contiguous with the existing
    boundary. However, the perimeter contiguity requirement can often be
    overcome with geometrical and legal cleverness, and the rule further allows
    a series of parcels to be annexed as a group for the purposes of
    establishing contiguity, so this rule isn&#39;t as effective as it might appear
    at first glance.
  &lt;/li&gt;
  &lt;li&gt;
    &lt;b&gt;The three-mile rule (§31-12-105(1)(e)).&lt;/b&gt; No annexation can extend a
    municipal boundary more than three miles in any direction in a single year.
    This is critical for understanding many annexations. By strategic use of
    flagpole annexations, the potential expansion area can be greatly increased
    with a minimal investment, maximizing a municipality&#39;s options for further
    annexations.
  &lt;/li&gt;
  &lt;li&gt;
    &lt;b&gt;Enclave annexation (§31-12-106(1)).&lt;/b&gt; If a city completely surrounds a
    piece of unincorporated land, it may annex it without the usual hearing and
    petition process &amp;mdash; but only if the surrounding territory is
    substantial and more than just a right-of-way such as a highway (to prevent
    use of flagpoling to annex land without the usual process).
  &lt;/li&gt;
  &lt;li&gt;
    &lt;b&gt;Competing municipal claims (§31-12-114).&lt;/b&gt; There is a process for
    resolving disputes between two municipalities that want the same territory,
    but it is highly weighted in favor of the municipality with more than
    two-thirds boundary contiguity. This adds an extra dimension to the game &amp;mdash;
    municipalities must think strategically about arranging boundary contiguity
    for future land grabs before their rivals can do so.
  &lt;/li&gt;
&lt;/ol&gt;

&lt;!--
Ugh, no good way to link to CRS...

https://advance.lexis.com/documentpage/?pdmfid=1000516&amp;crid=5d6a2ad8-5dba-4f62-9754-26e619047c3c&amp;nodeid=ABHAAEAABAABAAB&amp;nodepath=%2FROOT%2FABH%2FABHAAE%2FABHAAEAAB%2FABHAAEAABAAB%2FABHAAEAABAABAAB&amp;level=5&amp;haschildren=&amp;populated=false&amp;title=31-12-101.+Short+title.&amp;config=014FJAAyNGJkY2Y4Zi1mNjgyLTRkN2YtYmE4OS03NTYzNzYzOTg0OGEKAFBvZENhdGFsb2d592qv2Kywlf8caKqYROP5&amp;pddocfullpath=%2Fshared%2Fdocument%2Fstatutes-legislation%2Furn%3AcontentItem%3A61P5-WX51-DYDC-J3Y6-00008-00&amp;ecomp=6gf59kk&amp;prid=24bb720c-4749-42e0-beda-871c99ce92b5

C.R.S. 31-12-101
https://advance.lexis.com/api/document/collection/statutes-legislation/id/61P5-WX51-DYDC-J3Y6-00008-00?cite=C.R.S.%2031-12-101&amp;context=1000516
# requires login when used in private window?!
--&gt;

&lt;!-- incentives vs rules = flagpoling --&gt;

&lt;div class=&#34;photo&#34;&gt;
  &lt;img src=&#34;https://cafbit.com/resource/game_of_zones/goboard.webp&#34; alt=&#34;A Go board with a game of Go being played&#34; /&gt;
  &lt;p&gt;
    The municipal annexation maneuvers to gain territory often seem like a game
    of Go.
  &lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
  The cleverness employed by municipalities to work around the rules creates
  bizarre, gerrymandered shapes where the city technically satisfies a
  contiguity requirement but clearly isn&#39;t engaging in orderly growth.
  Sometimes I wonder if municipalities feel more emboldened to make such
  opportunistic annexations because people seldom see these crazy boundaries on
  modern maps.
&lt;/p&gt;

&lt;p&gt;
  As municipalities grow toward each other, annexation becomes a competitive
  sport where municipalities are pressured to &#34;call dibs&#34; on land before
  someone else does. Annexations become a game of &lt;a
    href=&#34;https://en.wikipedia.org/wiki/Go_(game)&#34;&gt;Go&lt;/a&gt;
  where each player tries to gain as much territory as they can, while also
  trying to block their opponent from gaining territory with strategic
  defensive annexations.&lt;sup&gt;&lt;a href=&#34;#goz-footnote-4&#34;&gt;[4]&lt;/a&gt;&lt;/sup&gt; The result
  is piecemeal, bizarrely shaped franken-cities.
&lt;/p&gt;

&lt;h2 style=&#34;clear: both;&#34;&gt;Observations&lt;/h2&gt;

&lt;p&gt;
  Let&#39;s take a look at a few interesting things on the map.
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/johnstown.webp&#34; alt=&#34;Map showing Johnstown&#39;s fragmented municipal boundaries spread across multiple disconnected areas&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  Johnstown may be the poster child of fragmented annexation. I regularly hear
  people express surprise about the places that are considered Johnstown. Shall
  we meet in Johnstown, or Johnstown, or Johnstown, or Johnstown? (Or the
  Buc-ee&#39;s?)
&lt;/p&gt;


&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/mead.webp&#34; alt=&#34;Map showing Mead&#39;s municipal boundaries elongated along I-25&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  The folks in Mead sure love themselves some I-25. Everyone wants that sweet,
  sweet high value land adjacent to Coloradans&#39; favorite highway. The land to
  the east and west of Mead... not so much.
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/berthoud.webp&#34; alt=&#34;Map showing Berthoud&#39;s flagpole annexation extending east to reach I-25&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  Small towns like Berthoud that settled along the old highway may enjoy some
  quaint charm, but miss out on the economic opportunities provided by the
  bustling freeway. But why settle? Thanks to flagpole annexation, you can
  truly have it all!
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/loveland-fort-collins.webp&#34; alt=&#34;Map showing the intentional gap between Fort Collins and Loveland city limits&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  I was surprised to see this gap between Fort Collins and Loveland. It seems a
  bit unlikely given the immense growth in the area, and it looks just a little
  bit too regular.
  It turns out that this is an intentional &#34;&lt;a
    href=&#34;https://www.larimer.org/sites/default/files/uploads/2017/plan_for_the_region_between_fort_collins_and_loveland.pdf&#34;&gt;community
    separation&lt;/a&gt;&#34; agreement meant to preserve the &#34;physical and visual
  separation&#34; between the two cities. From the looks of the rest of the
  map, I&#39;m guessing this idea didn&#39;t really catch on elsewhere.
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/greeley.webp&#34; alt=&#34;Map showing Greeley expanding westward toward I-25 and Windsor blocking its path&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  All the major Northern Colorado cities have an attraction to I-25. Greeley&#39;s
  original town site is now at the extreme eastern side of the city&#39;s current
  boundaries, as the city desperately tries to reach westward towards I-25. But
  wait, what&#39;s that to the west? In a bold power move, Windsor has leaped south
  with just enough annexation to block Greeley&#39;s expansion! (At least north of
  US-34.)
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/erie.webp&#34; alt=&#34;Map showing Erie&#39;s municipal boundaries with a flagpoled fence enclosing territory in the northeast&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  Erie, my fair town, is expected to expand throughout the remaining
  unincorporated land in this square of highways, according to its planning
  area boundary. But the planning area is largely an aspirational signaling of
  intent without any real legal teeth. So some of these adjacent municipalities
  could make a power move into the square, especially if Erie manages to upset
  a neighbor like Lafayette. (&lt;a
    href=&#34;https://www.andrewsawusch.com/erie-s-iga-s-and-local-governmental-relations-including-nine-mile&#34;&gt;Again&lt;/a&gt;.)
&lt;/p&gt;

&lt;p&gt;
  Notice the flagpoled fence in the northeast part of the map. Someone at Erie
  is truly a master of Go, and understands that controlling a territory does
  not require &lt;em&gt;occupying&lt;/em&gt; it, but rather merely &lt;em&gt;surrounding&lt;/em&gt; it.
  Because the surrounding territory consists of flagpoles instead of
  substantial land, Colorado law does not permit a trivial &#34;enclave annexation&#34;
  of the interior which would skip the usual annexation process. Nonetheless,
  this annexation strategy is quite effective at protecting the enclave from
  invading rivals.
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/thornton.webp&#34; alt=&#34;Map showing Thornton&#39;s territory surrounding Northglenn on multiple sides&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  Thornton used to be firmly south of Northglenn. Apparently while Northglenn
  was sleeping, Thornton annexed all remaining unincorporated land around it,
  cutting Northglenn off from future expansion, and paving the way for
  Thornton&#39;s future territorial ambitions to the northeast.
&lt;/p&gt;

&lt;p&gt;
  But wait a second... what&#39;s that bit of land at the top of the map that&#39;s shaded the same color as Northglenn?
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/northglenn.webp&#34; alt=&#34;Map showing Northglenn&#39;s Section 36 exclave six miles north of the main city&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  Surprisingly, Northglenn&#39;s city limits include a satellite exclave a full six
  miles north of what would otherwise be the city&#39;s northern boundary, in Weld
  County! This is Northglenn&#39;s
  &lt;a href=&#34;https://www.northglenn.org/government/land_use_and_zoning/section_36_area_plan.php&#34;&gt;&#34;Section 36&#34;&lt;/a&gt;
  area. How it was legally annexed is beyond me. It certainly wouldn&#39;t be legal
  with today&#39;s annexation laws. Perhaps the laws were different at the time, or
  it was somehow part of the original 1969 incorporation. Either way, this
  territory truly puts the &#34;North&#34; in &#34;Northglenn&#34;!
&lt;/p&gt;

&lt;p&gt;
  Northglenn operates a water treatment plant in this area, but I&#39;m baffled at
  why they felt the need to include it in their political jurisdiction. After
  all, cities are free to own and operate infrastructure in other cities or
  unincorporated areas. In fact, Northglenn&#39;s utility GIS shows that they
  operate a &lt;a
    href=&#34;https://www.arcgis.com/apps/mapviewer/index.html?layers=54935c16e76340d8814013882c36e9f8&#34;&gt;6-mile force
    main&lt;/a&gt; connected to this water treatment plant that passes through
  northern Thornton. (Yes, this means that Northglenn literally pumps their
  sewage 6 miles away to a whole other county. Maybe they figure Weld County
  already smells funny, anyway? I kid, I kid...)
&lt;/p&gt;

&lt;p&gt;
  As far as I can tell, Section 36 contains exactly one residential parcel with
  a house. I&#39;m imagining the Weld County clerks grumbling about having to make
  a special election ballot including Northglenn items just for whoever lives
  in that one house.
&lt;/p&gt;

&lt;p&gt;
  Sadly for Northglenn, current Colorado law (C.R.S. §31-12-104(2)(a)) would
  seem to legally prevent Northglenn from expanding outward from Section 36,
  since the exclave could not be used for meeting contiguity requirements.
  Based on published planning area boundaries, it would seem that Northglenn&#39;s
  arch nemesis Thornton is destined to surround Northglenn yet again.
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/severance.webp&#34; alt=&#34;Map showing Severance&#39;s strategic flagpole annexations extending in multiple directions&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  Severance (pop. ~10,000), through a series of strategic flagpole annexations
  and the three-mile rule, has a
  &lt;a href=&#34;https://townofseverance.org/DocumentCenter/View/261/Future-Land-Use-Map-PDF&#34;&gt;
  published planning area&lt;/a&gt;
  (which includes potential future annexations) that is a whopping 78+ square
  miles &amp;mdash; far larger than the existing city of Fort Collins! It&#39;s a great
  example of how to carefully arrange current annexations to maximize the
  potential for future annexations under Colorado law.
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/carbon-valley.webp&#34; alt=&#34;Map showing the Carbon Valley towns of Firestone, Frederick, and Dacono expanding away from each other&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  The original town sites of the three Carbon Valley towns (Firestone,
  Frederick, and Dacono) were very close to each other, which has led the towns
  to expand away from each other (north, west, and south, respectively), with
  the ensuing annexations naturally including plenty of land around I-25.
&lt;/p&gt;

&lt;p class=&#34;centered&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/game_of_zones/brighton.webp&#34; alt=&#34;Map showing Brighton&#39;s flagpole annexations toward the E-470 loop&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
  Even Brighton is looking to flagpole its way into some of that lucrative
  &#34;inside the 470 loop, adjacent to highways&#34; land. Similar to Erie&#39;s maneuver,
  they&#39;ve managed to surround a large chunk of unannexed land to the south to
  keep Commerce City from getting all up in their business.
&lt;/p&gt;

&lt;h2&gt;The shape of things to come&lt;/h2&gt;

&lt;p&gt;
  Most municipalities maintain a plan for how they will manage land acquired in
  potential future annexations, as required by C.R.S. §31-12-105(1)(e)(I) if
  they are interested in annexing. The planning areas defined by these plans
  provide an interesting glimpse into the future annexation ambitions of these
  municipalities. I was curious what the map would look like if instead of
  using municipal boundaries, I drew the municipalities according to their
  planning areas. I gathered planning area boundaries&lt;sup&gt;&lt;a
    href=&#34;#goz-footnote-5&#34;&gt;[5]&lt;/a&gt;&lt;/sup&gt;
  for most of the municipalities in the I-25 and US-85 corridors, and used them
  to render the below map.
&lt;/p&gt;

&lt;div class=&#34;figure&#34;&gt;
  &lt;a href=&#34;https://cafbit.com/resource/game_of_zones/north-front-range-future.webp&#34;&gt;
    &lt;!-- Just inline the full size image so it looks okay on Retina displays. --&gt;
    &lt;!--
    &lt;img src=&#34;https://cafbit.com/resource/game_of_zones/north-front-range-future-thumb.webp&#34; /&gt;
    --&gt;
    &lt;img src=&#34;https://cafbit.com/resource/game_of_zones/north-front-range-future.webp&#34; alt=&#34;Map of municipal planning areas from Denver to Fort Collins showing overlapping future annexation claims&#34; /&gt;
&lt;/a&gt;
  &lt;p&gt;
    This map shows planning areas (as opposed to current political boundaries) for
    many municipalities in the I-25 and US-85 corridors. Areas in grey indicate
    land where the planning area boundaries overlap (and where future municipal
    battles will be fought?).
  &lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
  This map is, of course, complete fiction. Towns are pressured into drafting
  broad planning areas within the Colorado three-mile rule to keep their
  options open. It&#39;s no real indication that these areas will ever be
  incorporated or developed. Still, one wonders if the continuous stream of
  cities depicted here could be part of some future &#34;Chey-buquerque&#34;
  megalopolis.
&lt;/p&gt;

&lt;h2&gt;Footnotes&lt;/h2&gt;

&lt;ol class=&#34;footnote&#34;&gt;
  &lt;li id=&#34;goz-footnote-1&#34;&gt;
    I know you can actually see municipal boundaries on Google Maps, one city
    at a time, if you select the city. I don&#39;t think this is a very
    satisfactory experience, since it doesn&#39;t work at all zoom levels, and only
    seeing a single boundary at a time doesn&#39;t effectively visualize the
    interesting territorial maneuvers that may be playing out between cities.
  &lt;/li&gt;
  &lt;li id=&#34;goz-footnote-2&#34;&gt;
    Understanding municipal territory may be becoming more of a practical
    matter, though. People like to use city names to refer to places. As cities
    grow and city limits become more convoluted, it becomes harder for people
    to refer to places without confusion. If I&#39;m shopping in Orchard Town
    Center and tell someone I&#39;m in Westminster, I may need to clarify that with
    &#34;No, not the Westminster that&#39;s along the Boulder Turnpike... &lt;em&gt;the other
    Westminster&lt;/em&gt;.&#34;
  &lt;/li&gt;
  &lt;li id=&#34;goz-footnote-3&#34;&gt;
    I don&#39;t mean to imply that the individuals running the towns are
    necessarily conniving. But every organization exists in an economic context
    with financial pressure, and people under pressure tend to follow
    incentives. Incentives can produce very positive results in many
    organizations, since people are usually incentivized to cooperate,
    negotiate, compromise, and reach arrangements of mutual profit. Incentives
    can be problematic, though, when there is a power imbalance. Municipalities
    have the power of government and the authority to levy taxes &amp;mdash; a
    powerful capability that they have every incentive to leverage via annexation.
  &lt;/li&gt;
  &lt;li id=&#34;goz-footnote-4&#34;&gt;
    While municipalities will often make a good show of negotiating land use
    agreements with nearby municipalities in an effort to achieve harmony, the
    moment such agreements become inconvenient they may be &lt;a
      href=&#34;https://apoliticalhobbyistinlafayetteco.substack.com/p/deep-diving-at-287-and-arapahoe&#34;&gt;
      withdrawn and disputes handled in lengthy court battles instead&lt;/a&gt;.
  &lt;/li&gt;
  &lt;li id=&#34;goz-footnote-5&#34;&gt;
    Many of these planning area boundaries were available for download from the
    various municipal GIS systems. To handle the ones that were only available
    in PDF documents, I traced them using the excellent &lt;a
      href=&#34;https://geojson.io&#34;&gt;geojson.io&lt;/a&gt; tool.
  &lt;/li&gt;
&lt;/ol&gt;</description>
        </item>
    
        <item>
          <title>Implementing SCTP to support WebRTC data channels in pure Rust</title>
          <link>https://cafbit.com/post/rust_webrtc_data_channels/</link>
          <pubDate>Thu, 20 Sep 2018 15:45:23 -0600</pubDate>
          <guid>https://cafbit.com/post/rust_webrtc_data_channels/</guid>
          <description>
&lt;p&gt;
I recently talked at the
&lt;a href=&#34;https://www.meetup.com/Rust-Boulder-Denver/&#34;&gt;Denver Rust Meetup&lt;/a&gt;
about my side project to implement WebRTC data channels in Rust.  I&#39;ll
probably blog about this project in more detail in the future, but in
the meantime here are the slides and a short demo video.
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;&lt;a href=&#34;https://cafbit.com/resource/sctp/sctp-rust.pdf&#34;&gt;Presentation slides (PDF, 1.7MB)&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href=&#34;https://cafbit.com/resource/sctp/sctp-demo.mp4&#34;&gt;A quick video of the demo (MP4, 5.3MB)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
I also made the following informal &#34;studio&#34; video of the talk.  The live
version was probably better, but hopefully this is good enough to get the
points across.
&lt;/p&gt;

&lt;center&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube.com/embed/_Ixvl5BKjms?rel=0&#34; frameborder=&#34;0&#34; allow=&#34;autoplay; encrypted-media&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/center&gt;

</description>
        </item>
    
        <item>
          <title>Tokio internals: Understanding Rust&#39;s asynchronous I/O framework from the bottom up</title>
          <link>https://cafbit.com/post/tokio_internals/</link>
          <pubDate>Mon, 18 Dec 2017 06:35:38 -0700</pubDate>
          <guid>https://cafbit.com/post/tokio_internals/</guid>
          <description>
&lt;div class=&#34;photo&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/tokio/welcome_to_the_futures.jpg&#34; /&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a href=&#34;https://tokio.rs/&#34;&gt;Tokio&lt;/a&gt; is a Rust framework for developing
applications which perform asynchronous I/O &amp;mdash; an event-driven
approach that can often achieve better scalability, performance, and
resource usage than conventional synchronous I/O.  Unfortunately, Tokio
is notoriously difficult to learn due to its sophisticated abstractions.
Even after reading the tutorials, I didn&#39;t feel that I had internalized
the abstractions sufficiently to be able to reason about what was
actually happening.
&lt;/p&gt;
&lt;p&gt;
My prior experience with asynchronous I/O programming may have even
hindered my Tokio education.  I&#39;m accustomed to using the operating
system&#39;s selection facility (e.g. Linux epoll) as a starting point, and
then moving on to dispatch, state machines, and so forth.  Starting with
the Tokio abstractions with no clear insight into where and how the
underlying &lt;code&gt;epoll_wait()&lt;/code&gt; happens, I found it difficult to
connect all the dots.  Tokio and its future-driven approach felt like
something of a black box.
&lt;/p&gt;

&lt;p&gt;
Instead of continuing on a top-down approach to learning Tokio, I
decided to instead take a bottom-up approach by studying the source code
to understand exactly how the current concrete implementation drives the
progression from epoll events to I/O consumption within a
&lt;code&gt;Future::poll()&lt;/code&gt;.  I won&#39;t go into great detail about the
high-level usage of Tokio and futures, as that is better covered in the
&lt;a href=&#34;https://tokio.rs/docs/getting-started/tokio/&#34;&gt;existing
tutorials&lt;/a&gt;.  I&#39;m also not going to discuss the general problem of
asynchronous I/O beyond a short summary, since entire books could be
written on the subject.  My goal is simply to have some confidence that
futures and Tokio&#39;s polling work the way I expect.
&lt;/p&gt;

&lt;p&gt;
First, some important disclaimers.  Note that Tokio is actively being
developed, so some of the observations here may quickly become
out-of-date.  For the purposes of this study, I used &lt;code&gt;tokio-core
0.1.10&lt;/code&gt;, &lt;code&gt;futures 0.1.17&lt;/code&gt;, and &lt;code&gt;mio 0.6.10&lt;/code&gt;.
Since I wanted to understand Tokio at its lowest levels, I did not
consider higher-level crates like &lt;code&gt;tokio-proto&lt;/code&gt; and
&lt;code&gt;tokio-service&lt;/code&gt;.  The tokio-core event system itself has a
lot of moving pieces, most of which I avoid discussing in the interest
of brevity.  I studied Tokio on a Linux system, and some of the
discussion necessarily touches on platform-dependent implementation
details such as epoll.  Finally, everything mentioned here is my
interpretation as a newcomer to Tokio, so there could be errors or
misunderstandings.
&lt;/p&gt;

&lt;h2&gt;Asynchronous I/O in a nutshell&lt;/h2&gt;

&lt;p&gt;
Synchronous I/O programming involves performing I/O operations which
block until completion.  Reads will block until data arrives, and writes
will block until the outgoing bytes can be delivered to the kernel.
This fits nicely with conventional imperative programming, where a
series of steps are executed one after the other.  For example, consider
an HTTP server that spawns a new thread for each connection.  On this
thread, it may read bytes until an entire request is received (blocking
as needed until all bytes arrive), processes the request, and then write
the response (blocking as needed until all bytes are written).
This is a very straightforward approach.
The downside is that a distinct thread is needed for each
connection due to the blocking, each with its own stack.  In many cases
this is fine, and synchronous I/O is the correct approach.  However, the
thread overhead hinders scalability on servers trying to handle a very
large number of connections (see: &lt;a
href=&#34;https://en.wikipedia.org/wiki/C10k_problem&#34;&gt;the C10k problem&lt;/a&gt;),
and may also be excessive on low-resource systems handling a few
connections.
&lt;/p&gt;

&lt;p&gt;
If our HTTP server was written to use asynchronous I/O, on the other
hand, it might perform all I/O processing on a single thread.  All
active connections and the listening socket would be configured as
non-blocking, monitored for read/write readiness in an event loop, and
execution would be dispatched to handlers as events occur.  State and
buffers would need to be maintained for each connection.  If a handler
is only able to read 100 bytes of a 200-byte request, it cannot wait for
the remaining bytes to arrive, since doing so would prevent other
connections from making progress.  It must instead store the partial
read in a buffer, keep the state set to &#34;reading request&#34;, and return to
the event loop.  The next time the handler is called for this
connection, it may read the remainder of the request and transition to a
&#34;writing response&#34; state.  Implementing such a system can become hairy
very fast, with complex state machines and error-prone resource
management.
&lt;/p&gt;

&lt;p&gt;
The ideal asynchronous I/O framework would provide a means of writing
such I/O processing steps one after the other, as if they were blocking,
but behind the scenes generate an event loop and state machines.  That&#39;s
a tough goal in most languages, but Tokio brings us pretty close.
&lt;/p&gt;

&lt;h2&gt;The Tokio stack&lt;/h2&gt;

&lt;center&gt;
&lt;p&gt;
&lt;img src=&#34;https://cafbit.com/resource/tokio/tokio-stack.svg&#34;&gt;
&lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;
The Tokio stack consists of the following components:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;b&gt;The system selector.&lt;/b&gt;
Each operating system provides a facility for receiving I/O events, such
as epoll (Linux), &lt;code&gt;kqueue()&lt;/code&gt; (FreeBSD/Mac OS), or IOCP
(Windows).
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Mio - Metal I/O.&lt;/b&gt;
&lt;a href=&#34;https://docs.rs/mio/0.6.10/mio/&#34;&gt;Mio&lt;/a&gt; is a Rust crate that
provides a common API for low-level I/O by internally handling the
specific details for each operating system.  Mio deals with the
specifics of each operating system&#39;s selector so you don&#39;t have to.
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Futures.&lt;/b&gt;
&lt;a href=&#34;https://docs.rs/futures/0.1.17/futures/&#34;&gt;Futures&lt;/a&gt; provide a
powerful abstraction for representing things that have yet to happen.
These representations can be combined in useful ways to create composite
futures describing a complex sequence of events.  This abstraction is
general enough to be used for many things besides I/O, but in Tokio we
develop our asynchronous I/O state machines as futures.
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Tokio&lt;/b&gt;
The &lt;code&gt;&lt;a
href=&#34;https://docs.rs/tokio-core/0.1.10/tokio_core/&#34;&gt;tokio-core&lt;/a&gt;&lt;/code&gt;
crate provides the central event loop which integrates with Mio to
respond to I/O events, and drives futures to completion.
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Your program.&lt;/b&gt;
A program using the Tokio framework can construct asynchronous I/O
systems as futures, and provide them to the Tokio event loop for
execution.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Mio: Metal I/O&lt;/h2&gt;

&lt;p&gt;
Mio provides a low-level I/O API allowing callers to receive events such
as socket read/write readiness changes.  The highlights are:
&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;b&gt;Poll and Evented.&lt;/b&gt;
Mio supplies the &lt;code&gt;&lt;a
href=&#34;https://docs.rs/mio/0.6.10/mio/event/trait.Evented.html&#34;
&gt;Evented&lt;/a&gt;&lt;/code&gt; trait to represent anything that can be a source of
events.  In your event loop, you register a number of
&lt;code&gt;Evented&lt;/code&gt;&#39;s with a &lt;code&gt;&lt;a
href=&#34;https://docs.rs/mio/0.6.10/mio/struct.Poll.html&#34;
&gt;mio::Poll&lt;/a&gt;&lt;/code&gt; object, then call &lt;code&gt;&lt;a
href=&#34;https://docs.rs/mio/0.6.10/mio/struct.Poll.html#method.poll&#34;
&gt;mio::Poll::poll()&lt;/a&gt;&lt;/code&gt; to block until events have occurred on one
or more &lt;code&gt;Evented&lt;/code&gt; objects (or the specified timeout has
elapsed).
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;System selector.&lt;/b&gt;
Mio provides cross-platform access to the system selector, so that Linux
epoll, Windows IOCP, FreeBSD/Mac OS &lt;code&gt;kqueue()&lt;/code&gt;, and
potentially others can all be used with the same API.  The overhead
required to adapt the system selector to the Mio API varies.  Because
Mio provides a readiness-based API similar to Linux epoll, many parts of
the API can be one-to-one mappings when using Mio on Linux.  (For
example, &lt;code&gt;mio::Events&lt;/code&gt; essentially &lt;em&gt;is&lt;/em&gt; an array of
&lt;code&gt;struct epoll_event&lt;/code&gt;.)  In contrast, because Windows IOCP is
completion-based instead of readiness-based, a bit more adaptation is
required to bridge the two paradigms.  Mio supplies its own versions of
&lt;code&gt;std::net&lt;/code&gt; structs such as &lt;code&gt;TcpListener&lt;/code&gt;,
&lt;code&gt;TcpStream&lt;/code&gt;, and &lt;code&gt;UdpSocket&lt;/code&gt;.  These wrap the
&lt;code&gt;std::net&lt;/code&gt; versions, but default to non-blocking and provide
&lt;code&gt;Evented&lt;/code&gt; implementations which add the socket to the system
selector.
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Non-system events.&lt;/b&gt;
In addition to providing readiness of I/O sources, Mio can also indicate
readiness events generated in user-space.  For example, if a worker
thread finishes a unit of work, it can signal completion to the event
loop thread.  Your program calls &lt;code&gt;&lt;a
href=&#34;https://docs.rs/mio/0.6.10/mio/struct.Registration.html#method.new2&#34;
&gt;Registration::new2()&lt;/a&gt;&lt;/code&gt; to obtain a &lt;code&gt;(Registration,
SetReadiness)&lt;/code&gt; pair.  The &lt;code&gt;Registration&lt;/code&gt; object is an
&lt;code&gt;Evented&lt;/code&gt; which can be registered with Mio in your event
loop, and &lt;code&gt;&lt;a
href=&#34;https://docs.rs/mio/0.6.10/mio/struct.SetReadiness.html#method.set_readiness&#34;
&gt;set_readiness()&lt;/a&gt;&lt;/code&gt; can be called  on the
&lt;code&gt;SetReadiness&lt;/code&gt; object whenever readiness needs to be
indicated.  On Linux, non-system event notifications are implemented
using a pipe.  When &lt;code&gt;SetReadiness::set_readiness()&lt;/code&gt; is
called, a &lt;code&gt;0x01&lt;/code&gt; byte is written to the pipe.
&lt;code&gt;mio::Poll&lt;/code&gt;&#39;s underlying epoll is configured to monitor the
reading end of the pipe, so &lt;code&gt;epoll_wait()&lt;/code&gt; will unblock and
Mio can deliver the event to the caller.  Exactly one pipe is created
when &lt;code&gt;Poll&lt;/code&gt; is instantiated, regardless of how many (if any)
non-system events are later registered.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
Every &lt;code&gt;Evented&lt;/code&gt; registration is associated with a
caller-provided &lt;code&gt;usize&lt;/code&gt; value typed as &lt;code&gt;&lt;a
href=&#34;https://docs.rs/mio/0.6.10/mio/struct.Token.html&#34;
&gt;mio::Token&lt;/a&gt;&lt;/code&gt;, and this value is returned with events to
indicate the corresponding registration.  This maps nicely to the system
selector in the Linux case, since the token can be placed in the 64-bit
&lt;code&gt;epoll_data&lt;/code&gt; union which functions in the same way.
&lt;/p&gt;

&lt;p&gt;
To provide a concrete example of Mio operation, here&#39;s what happens
internally when we use Mio to monitor a UDP socket on a Linux system:
&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;b&gt;Create the socket.&lt;/b&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;socket&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;mio::net::UdpSocket::bind(&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;SocketAddr::new(&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;std::net::IpAddr::V4(std::net::Ipv4Addr::new(&lt;span style=&#34;color:#40a070&#34;&gt;127&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;,&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;)),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;2000&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;).unwrap();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
This creates a Linux UDP socket, wrapped in a
&lt;code&gt;std::net::UdpSocket&lt;/code&gt;, which itself is wrapped in a
&lt;code&gt;mio::net::UdpSocket&lt;/code&gt;.  The socket is set to be non-blocking.
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Create the poll.&lt;/b&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;poll&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;mio::Poll::new().unwrap();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
Mio initializes the system selector, readiness queue (for non-system
events), and concurrency protection.  The readiness queue initialization
creates a pipe so readiness can be signaled from user-space, and the
pipe&#39;s read file descriptor is added to the epoll.  When a
&lt;code&gt;Poll&lt;/code&gt; object is created, it is assigned a unique
&lt;code&gt;selector_id&lt;/code&gt; from an incrementing counter.
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Register the socket with the poll.&lt;/b&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;poll.register(&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;socket,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;mio::Token(&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;mio::Ready::readable(),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;mio::PollOpt::level()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;).unwrap();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The &lt;code&gt;UdpSocket&lt;/code&gt;&#39;s &lt;code&gt;Evented.register()&lt;/code&gt; function is
called, which proxies to a contained &lt;code&gt;EventedFd&lt;/code&gt; which adds
the socket&#39;s file descriptor to the poll selector (by ultimately using
&lt;code&gt;epoll_ctl(fepd, EPOLL_CTL_ADD, fd, &amp;epoll_event)&lt;/code&gt; where
&lt;code&gt;epoll_event.data&lt;/code&gt; is set to the provided token value).  When
a &lt;code&gt;UdpSocket&lt;/code&gt; is registered, its &lt;code&gt;selector_id&lt;/code&gt; is
set to the &lt;code&gt;Poll&lt;/code&gt;&#39;s, thus associating it with the selector.
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;b&gt;Call poll() in an event loop.&lt;/b&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;loop&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;poll.poll(&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;events,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;None&lt;/span&gt;).unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;event&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;in&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;events&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;handle_event(event);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;
The system selector (&lt;code&gt;epoll_wait()&lt;/code&gt;) and then the readiness
queue are polled for new events.  (The &lt;code&gt;epoll_wait()&lt;/code&gt; blocks,
but because non-system events trigger epoll via the pipe in addition to
pushing to the readiness queue, they will still be processed in a timely
manner.)  The combined set of events are made available to the caller
for processing.
&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Futures and Tasks&lt;/h2&gt;

&lt;p&gt;
&lt;a href=&#34;https://en.wikipedia.org/wiki/Futures_and_promises&#34;&gt;Futures&lt;/a&gt;
are techniques borrowed from functional programming whereby computation
that has yet to happen can be represented as a &#34;future&#34;, and these
individual futures can be combined to develop complex systems.  This is
useful for asynchronous I/O because the basic steps needed to perform
transactions can be modeled as such combined futures.  In the HTTP
server example, one future may read a request by reading bytes as they
become available until the end of the request is reached, at which time
a &#34;Request&#34; object is yielded.  Another future may process a request and
yield a response, and yet another future may write responses.
&lt;/p&gt;

&lt;p&gt;
In Rust, futures are implemented in the &lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/&#34;&gt;futures crate&lt;/a&gt;.  You
can define a future by implementing the &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/future/trait.Future.html&#34;
&gt;Future&lt;/a&gt;&lt;/code&gt; trait, which requires a &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/future/trait.Future.html#tymethod.poll&#34;
&gt;poll()&lt;/a&gt;&lt;/code&gt; method which is called as needed to allow the future
to make progress.  This method returns either an error, an indication that the
future is still pending thus &lt;code&gt;poll()&lt;/code&gt; should be called again
later, or a yielded value if the future has reached completion.  The
&lt;code&gt;Future&lt;/code&gt; trait also provides a great many combinators as
default methods.
&lt;/p&gt;

&lt;p&gt;
To understand futures, it is crucial to understand tasks, executors, and
notifications &amp;mdash;  and how they arrange for a future&#39;s
&lt;code&gt;poll()&lt;/code&gt; method to be called at the right time.  Every future
is executed within a &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/task/index.html&#34;
&gt;task&lt;/a&gt;&lt;/code&gt; context.  A task itself is directly associated with
exactly one future, but this future may be a composite future that
drives many contained futures.  (For example, multiple futures joined
into a single future using the &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/future/fn.join_all.html&#34;
&gt;join_all()&lt;/a&gt;&lt;/code&gt; combinator, or two futures executed in series
using the &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/future/trait.Future.html#method.and_then&#34;
&gt;and_then()&lt;/a&gt;&lt;/code&gt; combinator.)
&lt;!-- better wording for above --&gt;
&lt;/p&gt;

&lt;p&gt;
Tasks and their futures require an &lt;em&gt;executor&lt;/em&gt; to run.  An
executor is responsible for polling the task/future at the correct times
&amp;mdash; usually when it has been notified that progress can be made.
Such a notification happens when some other code calls the &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/executor/trait.Notify.html#tymethod.notify&#34;
&gt;notify()&lt;/a&gt;&lt;/code&gt; method of the provided object implementing the
&lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/executor/trait.Notify.html&#34;
&gt;futures::executor::Notify&lt;/a&gt;&lt;/code&gt; trait.  An example of this can be
seen in the extremely simple executor provided by the
&lt;code&gt;futures&lt;/code&gt; crate that is invoked when calling the &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/future/trait.Future.html#method.wait&#34;
&gt;wait()&lt;/a&gt;&lt;/code&gt; method on a future.  From &lt;a
href=&#34;https://github.com/alexcrichton/futures-rs/blob/0.1.17/src/task_impl/std/mod.rs#L233&#34;
&gt;the source code&lt;/a&gt;:
&lt;/p&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;233
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;234
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;235
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;236
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;237
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;238
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;239
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;240
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;241
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;242
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;243
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;244
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;245
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;246
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;247
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;248
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;249
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// Waits for the internal future to complete, blocking this thread&amp;#39;s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// execution until it does.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;///
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// This function will call `poll_future` in a loop, waiting for the future
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// to complete. When a future cannot make progress it will use
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// `thread::park` to block the current thread.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;wait_future&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;-&amp;gt; &lt;span style=&#34;color:#007020&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;&amp;lt;&lt;/span&gt;F::Item,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;F::Error&lt;span style=&#34;color:#666&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;ThreadNotify::with_current(&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;notify&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;loop&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.poll_future_notify(notify,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;)&lt;span style=&#34;color:#666&#34;&gt;?&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;Async::NotReady&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;notify.park(),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;Async::Ready(e)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;Ok&lt;/span&gt;(e),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;})&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
Given a &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/executor/struct.Spawn.html&#34;
&gt;futures::executor::Spawn&lt;/a&gt;&lt;/code&gt; object previously created to fuse a
task and future, this executor calls &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/executor/struct.Spawn.html#method.poll_future_notify&#34;
&gt;poll_future_notify()&lt;/a&gt;&lt;/code&gt; in a loop.  The provided
&lt;code&gt;Notify&lt;/code&gt; object becomes part of the task context and the
future is polled.  If a future&#39;s &lt;code&gt;poll()&lt;/code&gt; returns
&lt;code&gt;Async::NotReady&lt;/code&gt; indicating that the future is still
pending, it &lt;em&gt;must&lt;/em&gt; arrange to be polled again in the future.  It
can obtain a handle to its task via &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/task/fn.current.html&#34;
&gt;futures::task::current()&lt;/a&gt;&lt;/code&gt; and call the &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/task/struct.Task.html#method.notify&#34;
&gt;notify()&lt;/a&gt;&lt;/code&gt; method whenever the future can again make progress.
(Whenever a future is being polled, information about its associated
task is stored in a thread-local which can be accessed via
&lt;code&gt;current()&lt;/code&gt;.) In the above case, if the poll returns
&lt;code&gt;Async::NotReady&lt;/code&gt;, the executor will block until the
notification is received.  Perhaps the future starts some work on
another thread which will call &lt;code&gt;notify()&lt;/code&gt; upon completion, or
perhaps the &lt;code&gt;poll()&lt;/code&gt; itself calls &lt;code&gt;notify()&lt;/code&gt;
directly before returning &lt;code&gt;Async::NotReady&lt;/code&gt;.  (The latter is
not common, since theoretically a &lt;code&gt;poll()&lt;/code&gt; should continue
making progress, if possible, before returning.)
&lt;/p&gt;

&lt;p&gt;
The Tokio event loop acts as a much more sophisticated executor that
integrates with Mio events to drive futures to completion.  In this
case, a Mio event indicating socket readiness will result in a
notification that causes the corresponding future to be polled.
&lt;/p&gt;

&lt;p&gt;
Tasks are the basic unit of execution when dealing with futures, and are
essentially &lt;a href=&#34;https://en.wikipedia.org/wiki/Green_threads&#34;&gt;green
threads&lt;/a&gt; providing a sort of &lt;a
href=&#34;https://en.wikipedia.org/wiki/Cooperative_multitasking&#34;&gt;cooperative
multitasking&lt;/a&gt;, allowing multiple execution contexts on one operating
system thread.  When one task is unable to make progress, it will yield
the processor to other runnable tasks.  It is important to understand
that notifications happen at the task level and not the future level.
When a task is notified, it will poll its top-level future, which may
result in any or all of the child futures (if present) being polled.
For example, if a task&#39;s top-level future is a &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/future/fn.join_all.html&#34;
&gt;join_all()&lt;/a&gt;&lt;/code&gt; of ten other futures, and one of these futures
arranges for the task to be notified, all ten futures will be polled
whether they need it or not.
&lt;/p&gt;

&lt;!-- ====================================================================== --&gt;

&lt;h2&gt;Tokio&#39;s interface with Mio&lt;/h2&gt;

&lt;p&gt;
Tokio converts task notifications into Mio events by using Mio&#39;s
&#34;non-system events&#34; feature described above.  After obtaining a Mio
&lt;code&gt;(Registration, SetReadiness)&lt;/code&gt; pair for the task, it
registers the &lt;code&gt;Registration&lt;/code&gt; (which is an
&lt;code&gt;Evented&lt;/code&gt;) with Mio&#39;s poll, then wraps the
&lt;code&gt;SetReadiness&lt;/code&gt; object in a &lt;code&gt;MySetReadiness&lt;/code&gt; which
implements the &lt;code&gt;Notify&lt;/code&gt; trait.  From &lt;a
href=&#34;https://github.com/tokio-rs/tokio-core/blob/0.1.10/src/reactor/mod.rs#L791&#34;
&gt;the source code&lt;/a&gt;:
&lt;/p&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;791
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;792
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;793
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;794
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;795
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;796
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;797
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;798
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;MySetReadiness&lt;/span&gt;(mio::SetReadiness);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Notify&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;for&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;MySetReadiness&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;notify&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;_id: &lt;span style=&#34;color:#902000&#34;&gt;usize&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.&lt;span style=&#34;color:#40a070&#34;&gt;0.&lt;/span&gt;set_readiness(mio::Ready::readable())&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;              &lt;/span&gt;.expect(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;failed to set readiness&amp;#34;&lt;/span&gt;);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
In this way, task notifications are converted into Mio events, and can
be processed in Tokio&#39;s event handling and dispatch code along with
other types of Mio events.
&lt;/p&gt;

&lt;p&gt;
Just as Mio wraps &lt;code&gt;std::net&lt;/code&gt; structs such as
&lt;code&gt;UdpSocket&lt;/code&gt;, &lt;code&gt;TcpListener&lt;/code&gt;, and
&lt;code&gt;TcpStream&lt;/code&gt; to customize functionality, Tokio also uses
composition and decoration to provide Tokio-aware versions of these
types.  For example, Tokio&#39;s &lt;code&gt;UdpSocket&lt;/code&gt; looks something like
this:
&lt;/p&gt;
&lt;center&gt;
&lt;p&gt;
&lt;img src=&#34;https://cafbit.com/resource/tokio/udpsocket.svg&#34;&gt;
&lt;/p&gt;
&lt;/center&gt;
&lt;p&gt;
Tokio&#39;s versions of these I/O source types provide constructors that
require a handle to the event loop (&lt;code&gt;&lt;a
href=&#34;https://docs.rs/tokio-core/0.1.10/tokio_core/reactor/struct.Handle.html&#34;
&gt;tokio_core::reactor::Handle&lt;/a&gt;&lt;/code&gt;).  When instantiated, these
types will register their sockets with the event loop&#39;s Mio poll to
receive edge-triggered events with a newly assigned even-numbered token.
(More on this, below.) Conveniently, these types will also arrange for
the current task to be notified of read/write readiness whenever the
underlying I/O operation returns &lt;code&gt;WouldBlock&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Tokio registers several types of &lt;code&gt;Evented&lt;/code&gt;&#39;s with Mio, keyed
to specific tokens:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;
Token 0 (&lt;code&gt;TOKEN_MESSAGES&lt;/code&gt;) is used for Tokio&#39;s internal
message queue, which provides a means of removing I/O sources,
scheduling tasks to receive read/write readiness notifications,
configuring timeouts, and running arbitrary closures in the context of
the event loop.  This can be used to safely communicate with the event
loop from other threads.  For example, &lt;code&gt; &lt;a
href=&#34;https://docs.rs/tokio-core/0.1.10/tokio_core/reactor/struct.Remote.html#method.spawn&#34;
&gt;Remote::spawn()&lt;/a&gt;&lt;/code&gt; marshals the future to the event loop via
the message system.
&lt;/p&gt;
&lt;p&gt;
The message queue is implemented as a &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/sync/mpsc/index.html&#34;
&gt;futures::sync::mpsc&lt;/a&gt;&lt;/code&gt; stream.  As a &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/stream/trait.Stream.html&#34;
&gt;futures::stream::Stream&lt;/a&gt;&lt;/code&gt; (which is similar to a future,
except it yields a sequence of values instead of a single value), the
processing of this message queue is performed using the
&lt;code&gt;MySetReadiness&lt;/code&gt; scheme mentioned above, where the
&lt;code&gt;Registration&lt;/code&gt; is registered with the
&lt;code&gt;TOKEN_MESSAGES&lt;/code&gt; token.  When &lt;code&gt;TOKEN_MESSAGES&lt;/code&gt;
events are received, they are dispatched to the
&lt;code&gt;consume_queue()&lt;/code&gt; method for processing.  (Source: &lt;code&gt;&lt;a
href=&#34;https://github.com/tokio-rs/tokio-core/blob/0.1.10/src/reactor/mod.rs#L133&#34;
&gt;enum Message&lt;/a&gt;&lt;/code&gt;, &lt;code&gt;&lt;a
href=&#34;https://github.com/tokio-rs/tokio-core/blob/0.1.10/src/reactor/mod.rs#L403&#34;
&gt;consume_queue()&lt;/a&gt;&lt;/code&gt;)
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
Token 1 (&lt;code&gt;TOKEN_FUTURE&lt;/code&gt;) is used to notify Tokio that the
main task needs to be polled.  This happens when a notification occurs
which is associated with the main task.  (In other
words, the future passed to &lt;code&gt;Core::run()&lt;/code&gt; or a child thereof,
not a future running in a different task via &lt;code&gt;spawn()&lt;/code&gt;.) This
also uses a &lt;code&gt;MySetReadiness&lt;/code&gt; scheme to translate future
notifications into Mio events.  Before a future running in the main task
returns &lt;code&gt;Async::NotReady&lt;/code&gt;, it will arrange for a notification
to be sent later in a manner of its choosing.  When the resulting
&lt;code&gt;TOKEN_FUTURE&lt;/code&gt; event is received, the Tokio event loop will
re-poll the main task.
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
Even-numbered tokens greater than 1 (&lt;code&gt;TOKEN_START+key*2&lt;/code&gt;) are
used to indicate readiness changes on I/O sources.  The key is the
&lt;code&gt;Slab&lt;/code&gt; key for the associated &lt;code&gt;Core::inner::io_dispatch
Slab&amp;lt;ScheduledIo&amp;gt;&lt;/code&gt; element.  The Mio I/O source types
(&lt;code&gt;UdpSocket&lt;/code&gt;, &lt;code&gt;TcpListener&lt;/code&gt;, and
&lt;code&gt;TcpStream&lt;/code&gt;) are registered with such a token automatically
when the corresponding Tokio I/O source types are instantiated.
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
Odd-numbered tokens greater than 1 (&lt;code&gt;TOKEN_START+key*2+1&lt;/code&gt;)
are used to indicate that a spawned task (and thus its associated
future) should be polled.  The key is the &lt;code&gt;Slab&lt;/code&gt; key for the
associated &lt;code&gt;Core::inner::task_dispatch
Slab&amp;lt;ScheduledTask&amp;gt;&lt;/code&gt; element.  As with
&lt;code&gt;TOKEN_MESSAGES&lt;/code&gt; and &lt;code&gt;TOKEN_FUTURE&lt;/code&gt; events, these
also use the &lt;code&gt;MySetReadiness&lt;/code&gt; plumbing.
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;!-- ====================================================================== --&gt;

&lt;h2&gt;Tokio event loop&lt;/h2&gt;

&lt;p&gt;
Tokio, specifically &lt;code&gt;&lt;a
href=&#34;https://docs.rs/tokio-core/0.1.10/tokio_core/reactor/struct.Core.html&#34;
&gt;tokio_core::reactor::Core&lt;/a&gt;&lt;/code&gt;, provides the event loop to manage
futures and tasks, drive futures to completion, and interface with Mio
so that I/O events will result in the correct tasks being notified.
Using the event loop involves instantiating the &lt;code&gt;Core&lt;/code&gt; with
&lt;code&gt;&lt;a
href=&#34;https://docs.rs/tokio-core/0.1.10/tokio_core/reactor/struct.Core.html#method.new&#34;
&gt;Core::new()&lt;/a&gt;&lt;/code&gt; and calling &lt;code&gt;&lt;a
href=&#34;https://docs.rs/tokio-core/0.1.10/tokio_core/reactor/struct.Core.html#method.run&#34;
&gt;Core::run()&lt;/a&gt;&lt;/code&gt; with a single future.  The event loop will drive
the provided future to completion before returning.  For server
applications, this future is likely to be long-lived.  It may, for
example, use a &lt;code&gt;TcpListener&lt;/code&gt; to continuously accept new
incoming connections, each of which may be handled by their own future
running independently in a separate task created by &lt;code&gt;&lt;a
href=&#34;https://docs.rs/tokio-core/0.1.10/tokio_core/reactor/struct.Handle.html#method.spawn&#34;
&gt;Handle.spawn()&lt;/a&gt;&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
The following flow chart outlines the basic steps of the Tokio event
loop:
&lt;/p&gt;

&lt;center&gt;
&lt;p&gt;
&lt;img src=&#34;https://cafbit.com/resource/tokio/tokio-event-loop.svg&#34; style=&#34;padding: 20px 0&#34;&gt;
&lt;/p&gt;
&lt;/center&gt;

&lt;!-- ====================================================================== --&gt;

&lt;h2&gt;What happens when data arrives on a socket?&lt;/h2&gt;

&lt;p&gt;
A useful exercise for understanding Tokio is to examine the steps that
occur within the event loop when data arrives on a socket.  I was
surprised to discover that this ends up being a two-part process, with
each part requiring a separate epoll transaction in a
separate iteration of the event loop.  The first part responds to a
socket becoming read-ready (i.e., a Mio event with an even-numbered
token greater than one for spawned tasks, or &lt;code&gt;TOKEN_FUTURE&lt;/code&gt;
for the main task) by sending a notification to the task which is
interested in the socket.  The second part handles the notification
(i.e., a Mio event with an odd-numbered token greater than one) by
polling the task and its associated future.  We&#39;ll consider the steps in
a scenario where a spawned future is reading from a
&lt;code&gt;UdpSocket&lt;/code&gt; on a Linux system, from the top of the Tokio
event loop, assuming that a previous poll of the future resulted in a
&lt;code&gt;recv_from()&lt;/code&gt; returning a &lt;code&gt;WouldBlock&lt;/code&gt; error.
&lt;/p&gt;

&lt;center&gt;
&lt;p&gt;
&lt;img src=&#34;https://cafbit.com/resource/tokio/recv-sequence-1.svg&#34;&gt;
&lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;
The Tokio event loop calls &lt;code&gt;mio::Poll::poll()&lt;/code&gt;, which in turn
(on Linux) calls &lt;code&gt;epoll_wait()&lt;/code&gt;, which blocks until some
readiness change event occurs on one of the monitored file descriptors.
When this happens, &lt;code&gt;epoll_wait()&lt;/code&gt; returns an array of
&lt;code&gt;epoll_event&lt;/code&gt; structs describing what has occurred, which are
translated by Mio into &lt;code&gt;mio::Events&lt;/code&gt; and returned to Tokio.
(On Linux, this translation should be zero-cost, since
&lt;code&gt;mio::Events&lt;/code&gt; is just a single-tuple struct of a
&lt;code&gt;epoll_event&lt;/code&gt; array.)  In our case, assume the only event in
the array is indicating read readiness on the socket.  Because the event
token is even and greater than one, Tokio interprets this as an I/O
event, and looks up the details in the corresponding element of
&lt;code&gt;Slab&amp;lt;ScheduledIo&amp;gt;&lt;/code&gt;, which contains information on any
tasks interested in read and write readiness for this socket.  Tokio
then notifies the reader task which, by way of the
&lt;code&gt;MySetReadiness&lt;/code&gt; glue described earlier, calls Mio&#39;s
&lt;code&gt;set_readiness()&lt;/code&gt;.  Mio handles this non-system event by
adding the event details to its readiness queue, and writing a single
&lt;code&gt;0x01&lt;/code&gt; byte to the readiness pipe.
&lt;/p&gt;

&lt;center&gt;
&lt;p&gt;
&lt;img src=&#34;https://cafbit.com/resource/tokio/recv-sequence-2.svg&#34;&gt;
&lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;
After the Tokio event loop moves to the next iteration, it once again
polls Mio, which calls &lt;code&gt;epoll_wait()&lt;/code&gt;, which this time
returns a read readiness event occurring on Mio&#39;s readiness pipe.  Mio
reads the &lt;code&gt;0x01&lt;/code&gt; which was previously written to the pipe,
dequeues the non-system event details from the readiness queue, and
returns the event to Tokio.  Because the event token is odd and greater
than one, Tokio interprets this as a task notification event, and looks
up the details in the corresponding element of
&lt;code&gt;Slab&amp;lt;ScheduledTask&amp;gt;&lt;/code&gt;, which contains the task&#39;s
original &lt;code&gt;Spawn&lt;/code&gt; object returned from &lt;code&gt;spawn()&lt;/code&gt;.
Tokio polls the task and its future via &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/executor/struct.Spawn.html#method.poll_future_notify&#34;
&gt;poll_future_notify()&lt;/a&gt;&lt;/code&gt;.  The future may then read data from
the socket until it gets a &lt;code&gt;WouldBlock&lt;/code&gt; error.
&lt;/p&gt;

&lt;p&gt;
This two-iteration approach involving a pipe write and read may add a little
overhead when compared to other asynchronous I/O event loops.  In
a single-threaded program, it is weird to look at the
&lt;code&gt;strace&lt;/code&gt; and see a thread use a pipe to communicate with
itself:
&lt;/p&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;pipe2&lt;/span&gt;([&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;], O_NONBLOCK&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;O_CLOEXEC) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;epoll_wait&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, [{EPOLLIN&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;EPOLLOUT, {u32&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;, u64&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;}}], &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\1&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;epoll_wait&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, [{EPOLLIN, {u32&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;4294967295&lt;/span&gt;, u64&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;18446744073709551615&lt;/span&gt;}}], &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\1&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;128&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7ffce1140f58&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;128&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;EAGAIN&lt;/span&gt; (Resource temporarily unavailable)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;recvfrom&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hello&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, {sa_family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;AF_INET, sin_port&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;htons&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;43106&lt;/span&gt;), sin_addr&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;inet_addr&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;)}, [&lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;]) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;recvfrom&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7f576621c800&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7ffce1140070&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7ffce114011c&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;EAGAIN&lt;/span&gt; (Resource temporarily unavailable)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;epoll_wait&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, [], &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;epoll_wait&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7f5765b24000&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;EINTR&lt;/span&gt; (Interrupted system call)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
Mio uses this pipe scheme to support the general case where
&lt;code&gt;set_readiness()&lt;/code&gt; may be called from other threads, and
perhaps it also has some benefits in forcing the fair scheduling of
events and maintaining a layer of indirection between futures and I/O.
&lt;/p&gt;

&lt;h2&gt;Lessons learned: Combining futures vs. spawning futures&lt;/h2&gt;

&lt;p&gt;
When I first started exploring Tokio, I wrote a small program to listen
for incoming data on several different UDP sockets.  I created ten
instances of a socket-reading future, each of them listening on a
different port number.  I naively joined them all into a single future
with &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/future/fn.join_all.html&#34;
&gt;join_all()&lt;/a&gt;&lt;/code&gt;, passed the combined future to
&lt;code&gt;Core::run()&lt;/code&gt;, and was surprised to discover that every
future was being polled whenever a single packet arrived.  Also somewhat
surprising was that &lt;code&gt;tokio_core::net::UdpSocket::recv_from()&lt;/code&gt;
(and its underlying &lt;code&gt;&lt;a
href=&#34;https://docs.rs/tokio-core/0.1.10/tokio_core/reactor/struct.PollEvented.html&#34;
&gt;PollEvented&lt;/a&gt;&lt;/code&gt;) was smart enough to avoid actually calling the
operating system&#39;s &lt;code&gt;recvfrom()&lt;/code&gt; on sockets that had not been
flagged as read-ready in a prior Mio poll.  The &lt;code&gt;strace&lt;/code&gt;,
reflecting a debug &lt;code&gt;println!()&lt;/code&gt; in my future&#39;s
&lt;code&gt;poll()&lt;/code&gt;, looked something like this:
&lt;/p&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;epoll_wait&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, [{EPOLLIN&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;EPOLLOUT, {u32&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;, u64&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;14&lt;/span&gt;}}], &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;5&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\1&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;epoll_wait&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, [{EPOLLIN, {u32&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;4294967295&lt;/span&gt;, u64&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;18446744073709551615&lt;/span&gt;}}], &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\1&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;128&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;read&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7ffc183129d8&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;128&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;EAGAIN&lt;/span&gt; (Resource temporarily unavailable)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;recvfrom&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;hello&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, {sa_family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;AF_INET, sin_port&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;htons&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;43106&lt;/span&gt;), sin_addr&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;inet_addr&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;)}, [&lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;]) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;getsockname&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, {sa_family&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;AF_INET, sin_port&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;htons&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;2006&lt;/span&gt;), sin_addr&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;inet_addr&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;)}, [&lt;span style=&#34;color:#40a070&#34;&gt;16&lt;/span&gt;]) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;recv 6 bytes from 127.0.0.1:43106 at 127.0.0.1:2006&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;52&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;52&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;recvfrom&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;12&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7f2a11c1c400&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7ffc18312ba0&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7ffc18312c4c&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;EAGAIN&lt;/span&gt; (Resource temporarily unavailable)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;write&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;UdpServer::poll()...&lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-weight:bold&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;21&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;epoll_wait&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, [], &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#40a070&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;epoll_wait&lt;/span&gt;(&lt;span style=&#34;color:#40a070&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;0x7f2a11c36000&lt;/span&gt;, &lt;span style=&#34;color:#40a070&#34;&gt;1024&lt;/span&gt;, &lt;span style=&#34;color:#666&#34;&gt;-&lt;/span&gt;&lt;span style=&#34;color:#40a070&#34;&gt;1&lt;/span&gt;) &lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt; ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
Since the concrete internal workings of Tokio and futures were somewhat
opaque to me, I suppose I hoped there was some magic routing happening
behind the scenes that would only poll the required futures.  Of course,
armed with a better understanding of Tokio, it&#39;s obvious that my program
was using futures  like this:
&lt;/p&gt;

&lt;center&gt;
&lt;p&gt;
&lt;img src=&#34;https://cafbit.com/resource/tokio/futures-join.svg&#34;&gt;
&lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;
This actually works fine, but is not optimal &amp;mdash; especially if you have a
lot of sockets.  Because notifications happen at the task level, any
notification arranged in any of the green boxes above will cause the
main task to be notified.  It will poll its &lt;code&gt;FromAll&lt;/code&gt; future,
which itself will poll each of its children.  What I really need is a
simple main future that uses &lt;code&gt;Handle::spawn()&lt;/code&gt; to launch each
of the other futures in their own tasks, resulting in an arrangement
like this:
&lt;/p&gt;

&lt;center&gt;
&lt;p&gt;
&lt;img src=&#34;https://cafbit.com/resource/tokio/futures-spawn.svg&#34;&gt;
&lt;/p&gt;
&lt;/center&gt;

&lt;p&gt;
When any future arranges a notification, it will cause only the future&#39;s
specific task to be notified, and only that future will be polled.
(Recall that &#34;arranging a notification&#34; happens automatically when
&lt;code&gt;tokio_core::net::UdpSocket::recv_from()&lt;/code&gt; receives
&lt;code&gt;WouldBlock&lt;/code&gt; from its underlying
&lt;code&gt;mio::net::UdpSocket::recv_from()&lt;/code&gt; call.) Future combinators
are powerful tools for describing protocol flow that would otherwise be
implemented in hand-rolled state machines, but it&#39;s important to
understand where your design may need to support separate tasks that
can make progress independently and concurrently.
&lt;/p&gt;

&lt;h2&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;
Studying the source code of Tokio, Mio, and futures has really helped
solidify my comprehension of Tokio, and validates my strategy of
clarifying abstractions through the understanding of their concrete
implementations.  This approach could pose a danger of only learning
narrow use cases for the abstractions, so we must consciously consider
the concretes as only being examples that shed light on the general
cases.  Reading the Tokio tutorials after studying the source code, I
find myself with a bit of a hindsight bias: Tokio makes sense, and
should have been easy to understand to begin with!
&lt;/p&gt;

&lt;p&gt;
I still have a few remaining questions that I&#39;ll have to research some
other day:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
Does Tokio deal with the starvation problem of edge triggering?  I
suppose it could be handled within the future by limiting the number of
read/writes in a single &lt;code&gt;poll()&lt;/code&gt;.  When the limit is reached,
the future could return early after explicitly notifying the current
task instead of relying on the implicit
&#34;schedule-on-&lt;code&gt;WouldBlock&lt;/code&gt;&#34; behavior of the Tokio I/O source
types, thus allowing other tasks and futures a chance to make progress.
&lt;/li&gt;
&lt;li&gt;
Does Tokio support any way of running the event loop itself on multiple
threads, instead of relying on finding opportunities to offload work to
worker threads to maximize use of processor cores?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
&lt;em&gt;
UPDATE 2017-12-19: There is a
&lt;a
href=&#34;https://www.reddit.com/r/rust/comments/7klghl/tokio_internals_understanding_rusts_asynchronous/&#34;
&gt;Reddit thread on r/rust&lt;/a&gt; discussing this post.  Carl Lerche, author
of Mio, has posted some informative comments
&lt;a
href=&#34;https://www.reddit.com/r/rust/comments/7klghl/tokio_internals_understanding_rusts_asynchronous/drfw5n1/&#34;
&gt;here&lt;/a&gt; and
&lt;a
href=&#34;https://www.reddit.com/r/rust/comments/7klghl/tokio_internals_understanding_rusts_asynchronous/drfwc1m/&#34;
&gt;here&lt;/a&gt;.  In addition to addressing the above questions, he notes that &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/stream/struct.FuturesUnordered.html&#34;
&gt;FuturesUnordered&lt;/a&gt;&lt;/code&gt; provides a means of combining futures such
that only the relevant child futures will be polled, thus avoiding
polling every future as &lt;code&gt;&lt;a
href=&#34;https://docs.rs/futures/0.1.17/futures/future/fn.join_all.html&#34;
&gt;join_all()&lt;/a&gt;&lt;/code&gt; would, with the tradeoff of additional
allocations.
Also, a future version of Tokio will be migrating away from the
&lt;code&gt;mio::Registration&lt;/code&gt; scheme for notifying tasks, which could
streamline some of the steps described earlier.
&lt;/em&gt;
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;
UPDATE 2017-12-21: It looks like Hacker News also had a
&lt;a href=&#34;https://news.ycombinator.com/item?id=15972593&#34;&gt;discussion of this post&lt;/a&gt;.
&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;

&lt;em&gt;
UPDATE 2018-01-26: I created a
&lt;a href=&#34;https://github.com/simmons/tokio-aio-examples&#34;&gt;GitHub repository&lt;/a&gt;
for my Tokio example code.
&lt;/em&gt;
&lt;/p&gt;
</description>
        </item>
    
        <item>
          <title>The Dream Machine, and highlights from the dawn of computing</title>
          <link>https://cafbit.com/post/dreammachine/</link>
          <pubDate>Wed, 25 Oct 2017 17:24:29 -0600</pubDate>
          <guid>https://cafbit.com/post/dreammachine/</guid>
          <description>
&lt;p&gt;
It&#39;s easy to imagine that computing sprang into existence with the
advent of home computers in the late 1970&#39;s and 1980&#39;s, just as many
people have the perception that the Internet sprang into existence in
the mid- to late-1990&#39;s.  In both cases, these technologies crossed
thresholds that made them accessible to general consumers, leading to
greatly increased usage that makes their pre-consumer existences seem
quite meager.  However, in the early days great minds were hard at work
on developing revolutionary ideas that are so ingrained in computing
today that they are largely taken for granted.
&lt;/p&gt;

&lt;p&gt;
I&#39;ve gained a much better appreciation for this pre-PC era of computing
after recently reading &lt;a href=&#34;http://a.co/0PU3P4G&#34;&gt;&lt;em&gt;The Dream Machine:
J.C.R. Licklider and the Revolution That Made Computing
Personal&lt;/em&gt;&lt;/a&gt;, written by M. Mitchell Waldrop and published in 2002.
While ostensibly a biography of J.C.R. Licklider, it actually devotes
more text to covering the contributions of many other pioneers,
including Norbert Wiener, Vannevar Bush, Claude Shannon, Alan Turing,
John von Neumann, John McCarthy, Douglas Engelbart, Bob Taylor, and Alan
Kay.  Licklider&#39;s life and career provide the book with a convenient
backbone since he crossed paths with so many other notable figures, and
also because of the book&#39;s focus on how these people helped bring about
Licklider&#39;s vision of interactive computing as a means of boosting human
productivity.
&lt;/p&gt;

&lt;p&gt;
I can definitely recommend this book to anyone interested in the history
of computing, as it clearly conveys how our modern world of computing
didn&#39;t arrive overnight but rather is the result of a long continuum of
ideas from throughout the 20th century.  In the words of the author:
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
I finally began to realize that windows, icons, mice, word processors,
spreadsheets, and all the other things that seem so important to the
modern software industry actually come at the end of the story, not at
the beginning.
&lt;/p&gt;
&lt;p class=&#34;cite&#34;&gt;
&amp;mdash; Waldrop, M. Mitchell. &lt;em&gt;The Dream Machine: J. C. R. Licklider and the
Revolution That Made Computing Personal&lt;/em&gt; (p. 472). Kindle edition. 
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
In this post, I&#39;ll share some notable highlights from this history that
seemed to fall into a few common themes that I found interesting.
&lt;/p&gt;

&lt;h2&gt;The time travelers&lt;/h2&gt;

&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/dreammachine/mother_of_all_demos-full.png&#34;&gt;&lt;img
src=&#34;https://cafbit.com/resource/dreammachine/mother_of_all_demos.png&#34; /&gt;&lt;/a&gt;
&lt;p&gt;
Douglas Engelbart delivers what was later known as
&lt;em&gt;The Mother of All Demos&lt;/em&gt; in 1968.
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
Some of the pioneers of computing were so far ahead of their time, that
they almost seem like time travelers from the future.
&lt;/p&gt;

&lt;ul&gt;

&lt;li&gt;
&lt;b&gt;Vannevar Bush&#39;s Memex.&lt;/b&gt;
In his 1939 draft article submitted to Fortune, Vannevar Bush described
a desktop device that would allow a user to instantly access a library
of printed material, all of which could be connected with links so the
user could effortlessly jump from one resource to another, with the goal
of enhancing the productivity of intellectual workers.  Although it
predates the World Wide Web by 52 years, it&#39;s astonishing how similar
Bush&#39;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Memex&#34;&gt;Memex&lt;/a&gt; system
was to hypertext and Wikipedia.  The Memex was described as an
electromechanical system based on microfilm.  While it was never built,
the idea inspired many later researchers.
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;The Mother of All Demos.&lt;/b&gt;
In 1968, Douglas Englebart delivered a groundbreaking technology
demonstration showing his team&#39;s work at Stanford Research Institute on
the &#34;oN-Line System&#34; (NLS) which introduced a number of new ideas such
as the mouse, a practical hypertext system, and a raster-scan video
output.  It integrated a number of pre-existing ideas such as word
processing to create a unique system for productivity and online
collaboration.  The demonstration itself was extraordinarily elaborate
for its day, featuring a 22-foot tall projector screen, microwave video
links back to SRI, and backstage video mixing.  It later came to be
known as
&lt;a href=&#34;https://en.wikipedia.org/wiki/The_Mother_of_All_Demos&#34;&gt;The
Mother of All Demos&lt;/a&gt;.  It&#39;s a testament to how far Englebart&#39;s vision
has become reality that, after reading about his presentation from 50
years ago, you can
&lt;a href=&#34;https://www.youtube.com/watch?v=yJDv-zdhzMY&#34;&gt;follow a link to
YouTube&lt;/a&gt; and be watching it in seconds.
&lt;/li&gt;

&lt;/ul&gt;


&lt;div style=&#34;clear: both;&#34;&gt;&lt;/div&gt;

&lt;h2&gt;World War II&lt;/h2&gt;

&lt;p&gt;
Reading the chapters that covered the 1930&#39;s and 1940&#39;s, I was struck at
how much progress was put on hold as World War II threw a colossal
&lt;a href=&#34;https://en.wikipedia.org/wiki/Non-maskable_interrupt&#34;&gt;
non-maskable interrupt&lt;/a&gt; at the scientists working on the foundations
of computing.  Industry and academia shifted gears to support the war
effort, and individual innovators put their computing projects aside
while they lent their skills to facing the imminent threats.  The author
concludes that the war ultimately forged the pieces of computer theory
&#34;into a unified whole&#34;.  (Ibid. p. 40) Nonetheless, the book contains a
number of examples where critical ideas were put on ice for the duration
of the war, such as:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;!-- Memex description before this? --&gt;
Vannevar Bush put his Memex research on hold in 1940 to create and lead
the National Defense Research Committee (NDRC) to organize scientific
research into defense technology.  Norbert Wiener proposed to include
digital computer research in the NDRC&#39;s scope, but Bush felt the need to
prioritize more immediately useful technology such as radar,
anti-aircraft fire control, anti-submarine warfare, and the atomic bomb.
&lt;!-- p. 30 --&gt;
It wasn&#39;t until 1945 that Bush returned to the topic and delivered his
influential essay,
&#34;&lt;a
href=&#34;https://www.theatlantic.com/magazine/archive/1945/07/as-we-may-think/303881/&#34;&gt;As
We May Think&lt;/a&gt;&#34;.
&lt;/li&gt;

&lt;li&gt;
&lt;!-- p. 33 --&gt;
Claude Shannon&#39;s 1937 master&#39;s thesis
&#34;&lt;a href=&#34;https://en.wikipedia.org/wiki/A_Symbolic_Analysis_of_Relay_and_Switching_Circuits&#34;&gt;A Symbolic Analysis of Relay and Switching Circuits&lt;/a&gt;&#34;
laid the foundation for digital computing, but his even more
revolutionary contributions would have to wait.  In 1941, he joined Bell
Labs and worked on anti-aircraft fire control and encrypted radio
systems during the day, and spent what time he could in the evenings
developing his ideas about the fundamentals of communication.  It wasn&#39;t
until 1948 that he published his ideas in
&#34;&lt;a href=&#34;https://en.wikipedia.org/wiki/A_Mathematical_Theory_of_Communication&#34;&gt;A Mathematical Theory of Communication&lt;/a&gt;&#34;
and became known as the father of Information Theory.
&lt;/li&gt;

&lt;li&gt;
&lt;!-- p. 37 --&gt;
John V. Atanasoff invented the first electronic digital computer
in 1939.  In 1942 he left academia to oversee the acoustic testing of
mines at the Naval Ordnance Laboratory, and continued to work in
non-computing fields after the war.
&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;
An interesting counterpoint is John von Neumann&#39;s career.  The war
led him to join the Manhattan Project, where his experience with
performing large-scale calculations on mechanical tabulators led him to
develop his ideas about electronic computing, ultimately leading to his
famous
&lt;a href=&#34;https://en.wikipedia.org/wiki/Von_Neumann_architecture&#34;&gt;von Neumann architecture&lt;/a&gt;.
&lt;/p&gt;

&lt;h2&gt;The things we take for granted&lt;/h2&gt;

&lt;p&gt;
Many ideas that seem obvious to us today were actually not obvious at
all, but rather had to be invented.  Some examples include:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;
&lt;b&gt;Interactive computing.&lt;/b&gt;
We take it for granted today that you use a computer by entering
commands (via the keyboard, mouse, or the touchscreen on your phone or
tablet), receive immediate feedback on the screen, then enter more
commands.  In the 1950&#39;s and 1960&#39;s, however, such a usage model was not
only uncommon, but actually controversial.
&lt;/p&gt;
&lt;p&gt;
One of the central themes of the book is Licklider&#39;s push for
interactive computing, where an operator can work with a computer in
real time to solve problems through the exploration of ideas, trial
and error, and rapid feedback.  This went against the prevailing idea of
the era that batch processing on centralized computers would always make
more sense.  Proponents of batch processing maintained that no matter
how inexpensive a unit of computation became, it would still be most
efficient to concentrate these resources in one giant computer that
could focus its entire capacity on performing a sequence of submitted
tasks one after the other.  Indeed, early attempts to provide
interactivity via time-sharing suffered from considerable overhead as
the processor had to switch between many users fast enough to maintain
the illusion that each user had his or her own computer.
Ultimately, the productivity benefits outweighed the overhead, and we
all use computers interactively today.
&lt;/p&gt;


&lt;!--
&#34;&lt;a href=&#34;https://en.wikipedia.org/wiki/Man-Computer_Symbiosis&#34;&gt;Man-Computer Symbiosis&lt;/a&gt;&#34;,


// TODO

that interactive computing 

The idea of interactive computing (as opposed to punch card batch processing)
- i.e., no matter how cheap computing got, it would always make economic sense to concentrate computing resources in one big unit.
--&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
&lt;b&gt;Programmability.&lt;/b&gt;
Even though Charles Babbage had described how a programmable machine
might be built in the 1830&#39;s, the concept was still exotic in the
1930&#39;s.  The idea that a machine might make a decision and choose
between alternate courses of action was quite radical and sounded eerily similar to thinking.
Thus, Howard Aiken&#39;s &lt;a href=&#34;https://en.wikipedia.org/wiki/Harvard_Mark_I&#34;&gt;Mark I&lt;/a&gt;,
one of the first programmable computers, was often called &#34;the
electronic brain&#34;.  (Interestingly, according to Wikipedia, loops were
initially implemented on the Mark I by physically creating loops of tape
so the same instructions could be fed to the processor repeatedly!)
&lt;/p&gt;
&lt;p&gt;
Today, programmability seems like the essence of computing.  But in
those days, even after they invented a means of implementing Babbage&#39;s
vision, it took a great deal of further thinking about how to harness
the power of programming.  In 1947, Herman H. Goldstine and John von
Neumann published &#34;&lt;a
href=&#34;https://library.ias.edu/files/pdfs/ecp/planningcodingof0103inst.pdf&#34;&gt;Planning
and Coding Problems for an Electronic Computing Instrument&lt;/a&gt;&#34; which
outlined techniques such as flow charting and subroutines, and software
engineering was born.  (Ibid. p. 87)
&lt;/p&gt;
&lt;p&gt;
Years later, in the 1950&#39;s, engineers were still struggling to grasp the
complexities of software:
&lt;/p&gt;
&lt;blockquote&gt;
Lincoln Lab&#39;s initial guess for the programming requirements on SAGE
&amp;mdash; that it would require perhaps a few thousand lines of computer
code to run the entire air-defense system &amp;mdash; was turning out to be
the most laughable underestimate of the whole project.  True, the
Lincoln Lab team was hardly alone in that regard.  Many computer
engineers still regarded programming as an afterthought: what could be
so hard about writing down a logical sequence of commands?
&lt;p class=&#34;cite&#34;&gt;
&amp;mdash; Waldrop, M. Mitchell. The Dream Machine: J. C. R. Licklider and the
Revolution That Made Computing Personal (p. 118). Kindle Edition. 
&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;
&lt;b&gt;Binary math.&lt;/b&gt;
We take it as a given today that binary is the most fundamental unit of
information and, given that electrical switches naturally hold a binary
state (off or on), the most elegant way of expressing values in a
computer.  This was not always obvious.  Designers of early computing
devices assumed that decimal arithmetic was the natural approach, as
each digit could store more information and no base conversion of inputs
and outputs was needed for the benefit of humans.
Manufacturers of mechanical calculators in the 1930&#39;s actually used
complex systems of gears to perform decimal arithmetic end-to-end.  Even
Aiken&#39;s Mark I, which was proposed in 1937 but not built until 1944,
operated directly on decimal numbers.
&lt;/p&gt;
&lt;p&gt;
Everything changed in 1937 with Claude Shannon&#39;s master&#39;s thesis,
&#34;&lt;a href=&#34;https://en.wikipedia.org/wiki/A_Symbolic_Analysis_of_Relay_and_Switching_Circuits&#34;&gt;A Symbolic Analysis of Relay and Switching Circuits&lt;/a&gt;&#34;,
which proposed binary-oriented digital circuits.
Independently in 1937 at Bell Labs, George Stibitz invented a binary
adding circuit.  Shannon&#39;s 1948 paper
&#34;&lt;a href=&#34;https://en.wikipedia.org/wiki/A_Mathematical_Theory_of_Communication&#34;&gt;A Mathematical Theory of Communication&lt;/a&gt;&#34;
established that the fundamental unit of information is the bit, a term
coined by his colleague J.W. Tukey, and the rest is history.
&lt;/p&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Skepticism&lt;/h2&gt;

&lt;p&gt;
New technology often faces skepticism and opposition from people
invested in the existing technology.
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;b&gt;Packet-switched networks.&lt;/b&gt;
People invested in the idea of circuit-switched communication were
highly resistant to the idea of packet switching.  The ARPANET designers
were routinely criticized by their Pentagon colleagues and AT&amp;amp;T
engineers for their decision to base their network on packet switching,
receiving comments such as &#34;this is how a telephone works...&#34;, &#34;there&#39;s
just no way this can work&#34;, and &#34;the buffers are going to run out&#34;.
(Ibid., p. 227)
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;Moore&#39;s Law.&lt;/b&gt;
Jacob Goldman, creator of Xerox&#39;s Palo Alto Research Center (PARC),
tried to explain Moore&#39;s Law to the pencil pushers at Xerox, but they
refused to believe that such a thing could even be possible.
(Ibid., p. 389)
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;Laser printers.&lt;/b&gt;
Goldman also struggled with convincing Xerox of the value of one of
PARC&#39;s legendary inventions, the laser printer.  Apparently many at
Xerox felt safer going with an alternative printing technology developed
by another team, which basically involved glueing a CRT screen to a
photocopier.  In the end, Goldman somehow managed to convince the
product selection committee to embrace the laser printer, which
eventually made billions of dollars for Xerox.
(Ibid. p. 392)
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;Internet.&lt;/b&gt;
As late as 1990, it was still hard to sell people on the value of the
Internet.  Notably, AT&amp;amp;T looked into the business potential of the
Internet, but concluded that it couldn&#39;t be profitable.
(Ibid., pp. 462-463)
&lt;/li&gt;

&lt;/ul&gt;


</description>
        </item>
    
        <item>
          <title>Cursive: Writing terminal applications in Rust</title>
          <link>https://cafbit.com/post/cursive_writing_terminal_applications_in_rust/</link>
          <pubDate>Thu, 24 Aug 2017 10:21:45 -0600</pubDate>
          <guid>https://cafbit.com/post/cursive_writing_terminal_applications_in_rust/</guid>
          <description>
&lt;p&gt;
As a learning exercise to sharpen my Rust programming skills, I recently
toyed with writing a small program that uses a terminal-based user
interface which I built using the &lt;a
href=&#34;https://crates.io/crates/cursive&#34;&gt;Cursive crate&lt;/a&gt; developed by
Alexandre Bury.  Cursive provides a high-level framework for building
event-driven terminal applications using visual components such as
menu bars, text areas, lists, dialog boxes, etc.  Conceptually,
developing with Cursive is one level of abstraction higher than using a
library such as ncurses, which provides a more raw interface to managing
screen contents and translating updates to the terminal&#39;s native
language.  In fact, Cursive defaults to using ncurses as one of several
possible backends, and allows setting themes to customize various text
colors and styles.
&lt;/p&gt;

&lt;h2&gt;Why write terminal applications?&lt;/h2&gt;

&lt;p&gt;
In today&#39;s software world, no one writes terminal applications expecting
them to be a hit with the masses.  Graphical applications (e.g. desktop
apps or web apps) provide a uniquely intuitive interface model that
allows users to quickly become productive with a minimal learning curve,
offer a high-bandwidth flow of information to the user, and remain the
only reasonable solution for many problem categories.  Many applications
would simply not be possible or practical without a GUI.
However, terminal programs can find a niche audience in technical users
such as software developers and system administrators who are often in
need of utilities that are a bit more two-dimensional than the command
line&#39;s standard input and output, but retain the flexibility to be
easily used remotely or on devices of limited capability.
&lt;/p&gt;

&lt;p&gt;
Also, terminal apps are often extremely &lt;em&gt;fast&lt;/em&gt; &amp;mdash; fast
enough to maintain the illusion of the computer being an extension of
the mind.  I find it frustrating that in 2017 I still spend plenty of
time waiting for the computer to do something. Occasionally even typing
into a text field in a web browser is laggy on my high-end late-model
iMac. For every extra cycle the hardware engineers give us, we software
engineers figure out some way to soak it up.
&lt;/p&gt;

&lt;p&gt;
The terminal is not for everyone, but lately I&#39;ve found it&#39;s the one
environment that is instantaneous enough that my flow is not thrown off.
For kicks, I recently installed XUbuntu on a $150 ARM Chromebook with
the idea of mostly just using the terminal (and having a throwaway
laptop that I&#39;m not scared to use on the bus/train). I expected to
mostly be using it as a dumb terminal to ssh into servers, but to my
surprise, it has actually proven to be very capable at performing a wide
range of local tasks in the terminal with good performance.
&lt;/p&gt;

&lt;h2&gt;The Cursive framework&lt;/h2&gt;

&lt;p&gt;
Anyone who has developed software with a GUI toolkit (e.g. Windows,
GTK+, Java Swing, Cocoa, etc.) will find most Cursive concepts to be
very familiar.  Visual components are called
&#34;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/views/index.html&#34;&gt;views&lt;/a&gt;&#34;
(some toolkits use use the terms &#34;widget&#34; or &#34;control&#34; for the same
concept), and are installed into a tree which is traversed when
rendering.  Some views may contain child views and are used for layout
(e.g. &lt;code&gt;BoxView&lt;/code&gt;
and &lt;code&gt;LinearLayout&lt;/code&gt;), while others are used as leaf nodes that
provide information or interact with the user (e.g. &lt;code&gt;Button&lt;/code&gt;,
&lt;code&gt;EditView&lt;/code&gt;, &lt;code&gt;TextView&lt;/code&gt;, &lt;code&gt;SliderView&lt;/code&gt;,
etc.).  Cursive can maintain multiple view trees as &#34;screens&#34; which can
be switched between.  Each screen&#39;s view tree has a
&lt;code&gt;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/views/struct.StackView.html&#34;&gt;StackView&lt;/a&gt;&lt;/code&gt;
as the root element, whose children are subtree &#34;layers&#34; that can be
pushed and popped.
&lt;/p&gt;

&lt;p&gt;
&lt;center&gt;
&lt;img src=&#34;https://cafbit.com/resource/cursive/cursive-demo.png&#34; /&gt;
&lt;/center&gt;
&lt;/p&gt;

&lt;p&gt;
Cursive provides an event model where the main program invokes
&lt;code&gt;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.run&#34;&gt;Cursive::run()&lt;/a&gt;&lt;/code&gt;
and the Cursive event loop will render views and dispatch to registered
callbacks (typically Rust closures) as needed until
&lt;code&gt;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.quit&#34;&gt;Cursive::quit()&lt;/a&gt;&lt;/code&gt;
is called, at which time the event loop exits.  Alternately, the main
program may choose to exercise more control by calling
&lt;code&gt;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.step&#34;&gt;Cursive::step()&lt;/a&gt;&lt;/code&gt;
as needed to perform a single iteration of input processing, event
dispatch, and view rendering.
&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/event/enum.Key.html&#34;&gt;Key
events&lt;/a&gt; are processed by whichever input view currently has focus,
and the user may cycle focus using the tab key.
&lt;/p&gt;

&lt;h2&gt;Referencing views&lt;/h2&gt;

&lt;p&gt;
Cursive diverges from other UI toolkits with respect to referencing
views.  In many environments, we would simply store references or
pointers to any views that we need to reference later, in addition to
whatever references are needed internally by the view tree to form the
parent-child relationships.  However, Rust&#39;s strict ownership model
requires us to be very explicit about how we allow multiple references
to the same memory.
&lt;/p&gt;

&lt;p&gt;
After the main program instantiates and configures a view object, it
generally adds it to the view tree by making it the child of an existing
view (e.g.
&lt;code&gt;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/views/struct.LinearLayout.html#method.add_child&#34;&gt;LinearLayout::add_child()&lt;/a&gt;&lt;/code&gt;)
or adding it to a screen&#39;s &lt;code&gt;StackView&lt;/code&gt; as a layer.  Rust
ownership of the object is moved at that time, and it is no longer
directly accessible to the main program.
&lt;/p&gt;

&lt;p&gt;
To access specific views after they have been integrated into a view
tree, views may be wrapped in an
&lt;code&gt;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/views/struct.IdView.html&#34;&gt;IdView&lt;/a&gt;&lt;/code&gt;
via &lt;code&gt;.with_id(&amp;amp;str)&lt;/code&gt; which allows them to be referenced
later using the provided string identifier.  A borrowed mutable
reference to the wrapped view may be retrieved with
&lt;code&gt;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.find_id&#34;&gt;Cursive::find_id()&lt;/a&gt;&lt;/code&gt;
or a closure operating on the view may be invoked with
&lt;code&gt;&lt;a href=&#34;https://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.call_on_id&#34;&gt;Cursive::call_on_id()&lt;/a&gt;&lt;/code&gt;.
Under the hood, these methods provide interior mutability by making use
of &lt;code&gt;RefCell&lt;/code&gt; and its runtime borrow checking to provide the
caller with a borrowed mutable reference.
&lt;/p&gt;

&lt;p&gt;
The following code demonstrates how views can be referenced by providing
a callback which copies text from one view to the other:
&lt;/p&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;extern&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;crate&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive::Cursive;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive::event::Key;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive::view::&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive::views::&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Cursive::new();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// Create a view tree with a TextArea for input, and a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// TextView for output.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;cursive.add_layer(LinearLayout::horizontal()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.child(BoxView::new(SizeConstraint::Fixed(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                            &lt;/span&gt;SizeConstraint::Fixed(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                            &lt;/span&gt;Panel::new(TextArea::new()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                &lt;/span&gt;.content(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                &lt;/span&gt;.with_id(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;))))&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;.child(BoxView::new(SizeConstraint::Fixed(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                            &lt;/span&gt;SizeConstraint::Fixed(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                            &lt;/span&gt;Panel::new(TextView::new(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                &lt;/span&gt;.with_id(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;)))));&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;cursive.add_global_callback(Key::Esc,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;c&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// When the user presses Escape, update the output view
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// with the contents of the input view.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;input&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;c.find_id::&lt;span style=&#34;color:#007020&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;lt&lt;/span&gt;;TextArea&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;).unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;output&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;c.find_id::&lt;span style=&#34;color:#007020&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;lt&lt;/span&gt;;TextView&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;).unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;output.set_content(input.get_content());&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;});&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;cursive.run();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;
Early in my exploration of Cursive, this method of accessing views
proved to be somewhat challenging since fetching references to two views
in the same lexical scope would result in &lt;code&gt;BorrowMutError&lt;/code&gt;
panics, since the internals of the second &lt;code&gt;find_id()&lt;/code&gt; would
try to mutably borrow a reference to the first view while traversing the
tree.  Cursive&#39;s view lookup code has since been
&lt;a href=&#34;https://github.com/gyscos/Cursive/commit/66af7fab7cf87adc5a1d1e074c6443d6d6071a54&#34;&gt;adjusted&lt;/a&gt;
so that this is no longer an issue.
&lt;/p&gt;

&lt;h2&gt;Model-View-Controller&lt;/h2&gt;

&lt;p&gt;
While developing a full application, I quickly ran into
&lt;code&gt;BorrowMutError&lt;/code&gt; panics again.
With application logic tied to my custom view implementations, and some
such code needing to call methods on other custom views, inevitably some
code would need to mutably borrow a view that was already borrowed
somewhere further up the stack.
&lt;/p&gt;

&lt;p&gt;
My solution was to completely decouple UI concerns from the application
logic, resulting in something along the lines of the well-known
Model-View-Controller (MVC) design pattern.  A &lt;code&gt;Ui&lt;/code&gt; struct
encapsulates all Cursive operations, and a &lt;code&gt;Controller&lt;/code&gt;
struct contains all application logic.  Each struct contains a message
queue which allows one to receive messages sent by the other.  These
messages are simple enums whose variants may contain associated data
specific to the message type.
&lt;/p&gt;

&lt;p&gt;
Instead of calling &lt;code&gt;Cursive::run()&lt;/code&gt;, the controller will
provide its own main loop where each iteration will operate as follows:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The controller main loop will call &lt;code&gt;Ui::step()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Ui::step()&lt;/code&gt; method will process any messages that
the controller may have added to its message queue.  These messages
allow the controller to change the UI state in various ways.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Ui::step()&lt;/code&gt; method will then step the Cursive UI
with &lt;code&gt;Cursive::step()&lt;/code&gt;.  Cursive will block until input is received.
Any pending UI events will be processed and any registered callbacks will be
executed.  Callbacks may result in messages being posted to the controller&#39;s
message queue (for example, the contents of a dialog box&#39;s form).&lt;/li&gt;
&lt;li&gt;The controller main loop will then process any messages that the UI
may have added to its message queue.  The controller may perform tasks
related to these messages, and optionally post messages to the UI&#39;s
message queue to indicate the outcome.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;
This scheme worked great for my needs where it&#39;s okay for the program to
completely block while waiting for user input.
&lt;/p&gt;

&lt;p&gt;
For the message queue, I used Rust&#39;s
&lt;a href=&#34;https://doc.rust-lang.org/std/sync/mpsc/&#34;&gt;
&lt;code&gt;std::sync::mpsc&lt;/code&gt;&lt;/a&gt; (multi-producer, single consumer FIFO
queue), which provides a convenient way for different code components to
own a cloned &lt;code&gt;Sender&lt;/code&gt; object which inserts elements into a
shared queue.  The use of &lt;code&gt;mpsc&lt;/code&gt; is really overkill for the
single-threaded applications I was working with, since any thread
synchronization work being performed is wasted.
&lt;/p&gt;

&lt;p&gt;
Here&#39;s an example of adapting the above text copy program to such an MVC
model.  It&#39;s admittedly much lengthier.
&lt;/p&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;  9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 28
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 29
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 30
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 31
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 32
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 33
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 34
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 35
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 36
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 37
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 38
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 39
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 40
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 41
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 42
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 43
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 44
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 45
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 46
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 47
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 48
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 49
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 50
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 51
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 52
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 53
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 54
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 55
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 56
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 57
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 58
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 59
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 60
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 61
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 62
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 63
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 64
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 65
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 66
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 67
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 68
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 69
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 70
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 71
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 72
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 73
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 74
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 75
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 76
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 77
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 78
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 79
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 80
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 81
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 82
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 83
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 84
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 85
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 86
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 87
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 88
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 89
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 90
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 91
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 92
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 93
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 94
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 95
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 96
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 97
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 98
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 99
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;100
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;101
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;102
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;103
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;104
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;105
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;106
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;107
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;108
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;109
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;110
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;111
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;112
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;113
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;114
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;115
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;116
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;117
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;118
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;119
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;120
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;121
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;122
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;123
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;124
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;125
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;126
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;127
&lt;/span&gt;&lt;span style=&#34;white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;128
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#f0f0f0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;extern&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;crate&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive::Cursive;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive::event::Key;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive::view::&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;cursive::views::&lt;span style=&#34;color:#666&#34;&gt;*&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;use&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;std::sync::mpsc;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;Ui&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;cursive: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;Cursive&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;ui_rx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;mpsc&lt;/span&gt;::Receiver&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;lt;UiMessage&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;ui_tx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;mpsc&lt;/span&gt;::Sender&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;lt;UiMessage&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;controller_tx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;mpsc&lt;/span&gt;::Sender&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;lt;ControllerMessage&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;UiMessage&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;UpdateOutput(&lt;span style=&#34;color:#007020&#34;&gt;String&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Ui&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// Create a new Ui object.  The provided `mpsc` sender will be used
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// by the UI to send messages to the controller.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;new&lt;/span&gt;(controller_tx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;mpsc&lt;/span&gt;::Sender&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;lt;ControllerMessage&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;-&amp;amp;&lt;/span&gt;gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Ui&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;(ui_tx,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;ui_rx)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;mpsc::channel::&lt;span style=&#34;color:#007020&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;lt&lt;/span&gt;;UiMessage&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;ui&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Ui&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;cursive: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;Cursive&lt;/span&gt;::new(),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;ui_tx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;ui_tx&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;ui_rx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;ui_rx&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;controller_tx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;controller_tx&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// Create a view tree with a TextArea for input, and a
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// TextView for output.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;ui.cursive.add_layer(LinearLayout::horizontal()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;.child(BoxView::new(SizeConstraint::Fixed(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                &lt;/span&gt;SizeConstraint::Fixed(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                &lt;/span&gt;Panel::new(TextArea::new()&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                    &lt;/span&gt;.content(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                    &lt;/span&gt;.with_id(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;))))&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;.child(BoxView::new(SizeConstraint::Fixed(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                &lt;/span&gt;SizeConstraint::Fixed(&lt;span style=&#34;color:#40a070&#34;&gt;10&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                &lt;/span&gt;Panel::new(TextView::new(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                                    &lt;/span&gt;.with_id(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;)))));&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// Configure a callback
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;controller_tx_clone&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;ui.controller_tx.clone();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;ui.cursive.add_global_callback(Key::Esc,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;move&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;c&lt;span style=&#34;color:#666&#34;&gt;|&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// When the user presses Escape, send an
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// UpdatedInputAvailable message to the controller.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;input&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;c.find_id::&lt;span style=&#34;color:#007020&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;lt&lt;/span&gt;;TextArea&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;input&amp;#34;&lt;/span&gt;).unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;text&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;input.get_content().to_owned();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;controller_tx_clone.send(&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;ControllerMessage::UpdatedInputAvailable(text))&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;.unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;});&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;ui&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// Step the UI by calling into Cursive&amp;#39;s step function, then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// processing any UI messages.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;step&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;amp;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;-&amp;amp;&lt;/span&gt;gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#902000&#34;&gt;bool&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;if&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;!&lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.cursive.is_running()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;return&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;false&lt;/span&gt;;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// Process any pending UI messages
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;while&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;Some&lt;/span&gt;(message)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.ui_rx.try_iter().next()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;message&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;UiMessage::UpdateOutput(text)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&amp;amp;&lt;/span&gt;gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;output&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.cursive&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                        &lt;/span&gt;.find_id::&lt;span style=&#34;color:#007020&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;lt&lt;/span&gt;;TextView&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;output&amp;#34;&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                        &lt;/span&gt;.unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                    &lt;/span&gt;output.set_content(text);&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// Step the UI
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.cursive.step();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;true&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;struct&lt;/span&gt; &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;Controller&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;rx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;mpsc&lt;/span&gt;::Receiver&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;lt;ControllerMessage&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;ui: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;Ui&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;enum&lt;/span&gt; &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;ControllerMessage&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;UpdatedInputAvailable(&lt;span style=&#34;color:#007020&#34;&gt;String&lt;/span&gt;),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;impl&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Controller&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// Create a new controller
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;new&lt;/span&gt;()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;-&amp;amp;&lt;/span&gt;gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;Result&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;lt;Controller,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;String&lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;(tx,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;rx)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;mpsc::channel::&lt;span style=&#34;color:#007020&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;lt&lt;/span&gt;;ControllerMessage&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;gt;();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;Ok&lt;/span&gt;(Controller&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;rx: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;rx&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;ui: &lt;span style=&#34;color:#0e84b5;font-weight:bold&#34;&gt;Ui&lt;/span&gt;::new(tx.clone()),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;})&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#4070a0;font-style:italic&#34;&gt;/// Run the controller
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;pub&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;run&lt;/span&gt;(&lt;span style=&#34;color:#666&#34;&gt;&amp;amp;&lt;/span&gt;amp;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;while&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.ui.step()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;while&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;Some&lt;/span&gt;(message)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.rx.try_iter().next()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// Handle messages arriving from the UI.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;message&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                    &lt;/span&gt;ControllerMessage::UpdatedInputAvailable(text)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&amp;amp;&lt;/span&gt;gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                        &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;self&lt;/span&gt;.ui&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                            &lt;/span&gt;.ui_tx&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                            &lt;/span&gt;.send(UiMessage::UpdateOutput(text))&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                            &lt;/span&gt;.unwrap();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;                &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;            &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;fn&lt;/span&gt; &lt;span style=&#34;color:#06287e&#34;&gt;main&lt;/span&gt;()&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#60a0b0;font-style:italic&#34;&gt;// Launch the controller and UI
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;let&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;controller&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;Controller::new();&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;match&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;controller&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;{&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;Ok&lt;/span&gt;(&lt;span style=&#34;color:#007020;font-weight:bold&#34;&gt;mut&lt;/span&gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;controller)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&amp;amp;&lt;/span&gt;gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;controller.run(),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;        &lt;/span&gt;&lt;span style=&#34;color:#007020&#34;&gt;Err&lt;/span&gt;(e)&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#666&#34;&gt;=&amp;amp;&lt;/span&gt;gt;&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;&lt;span style=&#34;color:#06287e&#34;&gt;println!&lt;/span&gt;(&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;Error: &lt;/span&gt;&lt;span style=&#34;color:#70a0d0&#34;&gt;{}&lt;/span&gt;&lt;span style=&#34;color:#4070a0&#34;&gt;&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#bbb&#34;&gt; &lt;/span&gt;e),&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#bbb&#34;&gt;    &lt;/span&gt;};&lt;span style=&#34;color:#bbb&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;h2&gt;Miscellaneous notes&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cursive is very much a work in progress and there are still
some rough edges to be worked out.  However, Alexandre Bury is lightning
fast at responding to bug reports and fixing issues.  &lt;a
href=&#34;https://github.com/gyscos/Cursive/issues/148&#34;&gt;One recent
issue&lt;/a&gt; I filed went from report to patch to commit in 14
minutes.&lt;/li&gt;
&lt;li&gt;It&#39;s unclear how you would develop a lightweight single-threaded
program that uses reactor-style asynchronous I/O dispatch.  For
example, a central &lt;code&gt;select()&lt;/code&gt; loop which dispatches
stdin/stdout events to Cursive, network socket events to other code,
and so on.  (I&#39;m not even sure if backends such as ncurses would even
support this.)&lt;/li&gt;
&lt;li&gt;I&#39;m also not sure how I would go about structuring
a multi-threaded application where the UI needs to process events from
other threads.   Cursive does provide a &lt;code&gt;&lt;a
href=&#34;https://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.set_fps&#34;&gt;Cursive::set_fps()&lt;/a&gt;&lt;/code&gt;
method which, in conjunction with &lt;code&gt;&lt;a
href=&#34;https://gyscos.github.io/Cursive/cursive/struct.Cursive.html#method.cb_sink&#34;&gt;Cursive::cb_sink()&lt;/a&gt;&lt;/code&gt;,
can poll for new events at specified time intervals.  But I&#39;ve always
preferred a purely event-driven design for such things instead of
needlessly burning cycles periodically while waiting.  (Again, there may be
complications at the ncurses layer.)&lt;/li&gt;
&lt;li&gt;Cursive wants callback closures to have static lifetime, which can
lead to some Rust puzzles if you&#39;d like to access non-static non-owned
items from within closures.  This may be inevitable, and the issue
mostly goes away with the MVC decoupling technique mentioned above.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
As a learning exercise, I wrote a
&lt;a href=&#34;https://github.com/simmons/tupm&#34;&gt;
Cursive-based interface to UPM password manager databases&lt;/a&gt;.  However,
nobody should use it for reasons outlined in its &lt;a
href=&#34;https://github.com/simmons/tupm/blob/master/README.md&#34;&gt;README&lt;/a&gt;.&lt;/p&gt;
</description>
        </item>
    
        <item>
          <title>Migrating from Apache Roller to Hugo and Isso</title>
          <link>https://cafbit.com/post/apache_roller_to_hugo_and_isso/</link>
          <pubDate>Tue, 06 Jun 2017 09:00:00 -0600</pubDate>
          <guid>https://cafbit.com/post/apache_roller_to_hugo_and_isso/</guid>
          <description>
&lt;p&gt;
After almost ten years of using &lt;a href=&#34;https://roller.apache.org/&#34;&gt;Apache
Roller&lt;/a&gt; to power this blog, I&#39;m making the leap to the &lt;a
href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; static site generator.  Roller served me
well, but after years of watching Roller+Tomcat use hundreds of megabytes of
memory on my server, I decided that it was overkill for my needs.&lt;sup&gt;&lt;a
href=&#34;#hugo-footnote-1&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; The only major feature which absolutely
demands dynamically generated pages is the comments, and I&#39;ve migrated that
functionally to a distinct service using &lt;a
href=&#34;https://posativ.org/isso/&#34;&gt;Isso&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
My goals are:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduce the server resource usage.&lt;/li&gt;
&lt;li&gt;Allow blog posts to be created, managed, and revisioned using the same
tools I use to manage software projects &amp;mdash; Vim, Git, etc.&lt;/li&gt;
&lt;li&gt;Reduce the deployment effort of the server-side software.  (Like many Go
apps, Hugo is a single statically linked binary with no dependencies to worry
about.)
&lt;/ul&gt;

&lt;p&gt;
For my own future benefit, I&#39;m providing my notes on this migration below.
&lt;/p&gt;

&lt;h2&gt;Migration steps&lt;/h2&gt;

&lt;p&gt;
Most of the migration process was straightforward, although a bit
time consuming.  I unfortunately don&#39;t have a &#34;roller-to-hugo&#34; script that
magically converts a blog, as several categories of content assets needed to be
manually adapted to the Hugo way of doing things.  I can outline the basic
steps, though:
&lt;/p&gt;

&lt;ol&gt;

&lt;li&gt;
&lt;b&gt;Create a Hugo theme.&lt;/b&gt;  I wanted the blog to look and feel the same in
Hugo as it did in Roller, so I needed to create a custom Hugo theme.  I was
already using custom stylesheets and &lt;a
href=&#34;http://velocity.apache.org/&#34;&gt;Velocity&lt;/a&gt; templates on Roller, so simply
extracting these assets from the database&#39;s &lt;code&gt;webpage&lt;/code&gt; table into files
got me most of the way there.  I then needed to touch up the files to convert
Velocity markup into &lt;a href=&#34;https://golang.org/pkg/html/template/&#34;&gt;Go
templates&lt;/a&gt; and adapt the pagination scheme.
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;Port blog posts.&lt;/b&gt;
Roller stores blog entries in the &lt;code&gt;weblogentry&lt;/code&gt; table, and their
associated tags in the &lt;code&gt;roller_weblogentrytag&lt;/code&gt; table.  I wrote a
one-off Python script to create Hugo content files out of this data.
&lt;!--
by using
the following PostgreSQL query:
&lt;pre class=&#34;code&#34;&gt;SELECT
    e.id,e.userid,anchor,title,text,
    to_char(pubtime at time zone &#39;UTC&#39;, &#39;YYYY-MM-DD\&#34;T\&#34;HH24:MI:SS\&#34;Z\&#34;&#39;) as pubtime,
    to_char(updatetime at time zone &#39;UTC&#39;, &#39;YYYY-MM-DD\&#34;T\&#34;HH24:MI:SS\&#34;Z\&#34;&#39;) as updatetime,
    e.websiteid,categoryid,publishentry,link,
    plugins,allowcomments,commentdays,righttoleft,
    pinnedtomain,locale,status,summary,
    content_type,content_src,
    string_agg(t.name,&#39;,&#39;) AS tags
FROM weblogentry AS e
LEFT JOIN roller_weblogentrytag AS t ON (e.id = t.entryid)
WHERE status = &#39;PUBLISHED&#39;
GROUP BY e.id;
&lt;/pre&gt;
--&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;Port static content.&lt;/b&gt;
This was simply a matter of finding the Roller &lt;code&gt;resources&lt;/code&gt; directory
in the filesystem, and copying it to the Hugo &lt;code&gt;static/resources&lt;/code&gt;
directory.
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;Port RSS and Atom feeds.&lt;/b&gt;
The current version of Hugo does not have built-in support for Atom feeds, so I
used a template-generated solution &lt;a
href=&#34;https://gist.github.com/lpar/7ded35d8f52fef7490a5be92e6cd6937&#34;&gt;as
described here&lt;/a&gt;.  I also needed to update the
&lt;code&gt;&amp;lt;head&amp;gt;&amp;lt;link&amp;nbsp;...&amp;nbsp;/&amp;gt;&amp;lt;/head&amp;gt;&lt;/code&gt; references
in my templates to point to the new feed URLs.
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;Port comments.&lt;/b&gt;
I used the &lt;a href=&#34;https://posativ.org/isso/&#34;&gt;Isso&lt;/a&gt; comment server to
support comments.  Isso works similarly to &lt;a
href=&#34;https://disqus.com/&#34;&gt;Disqus&lt;/a&gt;, except it is self-hosted.
&lt;ol class=&#34;inner&#34;&gt;
&lt;li&gt;Install Isso in a Docker container for isolation and ease of management.&lt;/li&gt;
&lt;li&gt;Map the blog&#39;s /isso URLs to Isso.&lt;/li&gt;
&lt;li&gt;Add the client HTML bits to inject the Isso comments into pages.&lt;/li&gt;
&lt;li&gt;Configure Isso: Basic configuration (dbpath, host, [server].listen),
logging, SMTP notifications, moderation, and guard settings (rate limits).
&lt;/li&gt;
&lt;li&gt;Import comments.  I wrote a one-off Python script to import comments,
paying careful attention to properly initialize the &lt;code&gt;voters&lt;/code&gt; Bloom
filter bitmask in Isso&#39;s SQLite database.
&lt;!--
based on the following query:
&lt;pre class=&#34;code&#34;&gt;SELECT
    e.anchor, c.name, c.email, c.url, c.content, c.remotehost,
    extract(&#39;epoch&#39; FROM c.posttime)
FROM roller_comment AS c
JOIN weblogentry AS e ON (e.id = c.entryid)
WHERE c.contenttype=&#39;text/html&#39; AND c.status=&#39;APPROVED&#39;;
&lt;/pre&gt;
--&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;

&lt;li&gt;
&lt;b&gt;Map old Roller URLs to Hugo URLs.&lt;/b&gt;  I configured some 301 (permanent)
redirects on my web server so that existing links to block posts and feed URLs
will continue to work.
&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;
I have a few ugly Python scripts for migrating data from Roller to Hugo/Isso,
but I&#39;ll hold off on posting them unless someone really wants to see them.
&lt;/p&gt;

&lt;h2&gt;Pros and cons&lt;/h2&gt;

&lt;p&gt;&lt;u&gt;Hugo pros:&lt;/u&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When I first started working through the &lt;a href=&#34;https://gohugo.io/overview/quickstart/&#34;&gt;Hugo Quickstart Guide&lt;/a&gt;, it seemed like a lot of steps.  However, after playing around with it for a while, everything seems really easy and straightforward.&lt;/li&gt;
&lt;li&gt;As expected, the resource usage is low.  Hugo is a single, self-contained ~6MB binary.  Since static pages are generated, there is no persistent resource usage.&lt;/li&gt;
&lt;li&gt;Blog posts can be composed completely offline, and tested using Hugo&#39;s built-in web server.  When ready, I can push the Git commit(s) and rebuild the site on the server.  Rebuilding my blog from scratch takes about 200 milliseconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;u&gt;Hugo cons:&lt;/u&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No built-in support for Atom feeds.  (But it&#39;s easy to add via a template.)&lt;/li&gt;
&lt;li&gt;It&#39;s not obvious how &lt;a
href=&#34;https://en.wikipedia.org/wiki/Trackback&#34;&gt;trackbacks&lt;/a&gt; would be
implemented with Hugo.&lt;/li&gt;
&lt;li&gt;Dynamic web apps have the luxury of providing the correct MIME type with
every document that is delivered.  Since Hugo is generating static files, I
now rely on the web server to determine the MIME type based on filename
extensions.  This may be an obstacle to preserving some URL schemes when
migrating to Hugo.&lt;sup&gt;&lt;a href=&#34;#hugo-footnote-2&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;
I ended up restructuring the web site to use Hugo-friendly URLs, and adding
permanent redirects to map old Roller URLs to Hugo URLs.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;u&gt;Isso pros:&lt;/u&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As a self-hosted solution, Isso avoids some of the privacy concerns that
people have with third-party solutions such as Disqus.&lt;/li&gt;
&lt;li&gt;Notification and moderation of comments via mail.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;u&gt;Isso cons:&lt;/u&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Isso is a very simple, no-frills service.  It accepts and regurgitates
comments, but not much more.&lt;/li&gt;
&lt;li&gt;There is no visible feedback when the guard rate-limits are hit, so the
user doesn&#39;t receive any hint about why the comment is not being posted.&lt;/li&gt;
&lt;li&gt;It doesn&#39;t seem practical to add the comment count below each entry on the
main page, as I did with Roller.&lt;/li&gt;
&lt;li&gt;I haven&#39;t figured out how to configure Isso to use my correct base URL in
mail notifications, so I have to tweak the URLs when approving or deleting
comments.  (The &lt;code&gt;host&lt;/code&gt; option seems to not be useful here.)&lt;/li&gt;
&lt;li&gt;
Isso seems to wake up every 500 milliseconds to do something, even when it is
not being actively used:
&lt;pre class=&#34;code&#34;&gt;
# strace -p 4890
strace: Process 4890 attached
select(5, [4], [], [], {0, 85673})      = 0 (Timeout)
select(5, [4], [], [], {0, 500000})     = 0 (Timeout)
select(5, [4], [], [], {0, 500000})     = 0 (Timeout)
select(5, [4], [], [], {0, 500000})     = 0 (Timeout)
select(5, [4], [], [], {0, 500000})     = 0 (Timeout)
&lt;/pre&gt;
Perhaps this is a function of &lt;a
href=&#34;http://werkzeug.pocoo.org/&#34;&gt;Werkzeug&lt;/a&gt;.  Despite the 500ms wakeup, the
CPU utilization seems to be negligible.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Footnotes&lt;/h2&gt;
&lt;ol class=&#34;footnote&#34;&gt;
&lt;li id=&#34;hugo-footnote-1&#34;&gt;
To be fair, there are probably lots of opportunities to tweak the parameters of
Tomcat and Roller to tune the resource usage.  Perhaps the JVM heap size and/or
the size of internal caches could be adjusted.  Also, memory usage of specific
services on Linux can be notoriously difficult to determine.  (Top is currently
showing that resident memory usage of my Tomcat server is 286MB.)
&lt;/li&gt;
&lt;li id=&#34;hugo-footnote-2&#34;&gt;
I suppose someone could manually add web server configuration rules to match
URL patterns to the right MIME types, but this seems needlessly manual and
brittle.
&lt;/li&gt;
&lt;li id=&#34;hugo-footnote-3&#34;&gt;
Isn&#39;t it fun reading through all the footnotes?
&lt;/li&gt;
&lt;/ol&gt;

</description>
        </item>
    
        <item>
          <title>Reinventing software for security; or: The woodpeckers are coming.</title>
          <link>https://cafbit.com/post/reinventing_software_for_security/</link>
          <pubDate>Tue, 06 Jan 2015 12:17:01 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/reinventing_software_for_security/</guid>
          <description>&lt;p&gt;
The past couple of years have been tough for digital security.  A few
disasters and near-disasters include:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Heartbleed&#34;&gt;Heartbleed&lt;/a&gt;, a
buffer over-read vulnerability in OpenSSL allowing unauthorized remote
access to data which may contain private keys.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Shellshock_%28software_bug%29&#34;&gt;Shellshock&lt;/a&gt;,
an issue with Bash allowing remote code execution in many varied
scenarios.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://technet.microsoft.com/en-us/library/security/MS14-066&#34;&gt;A
bug in Microsoft&#39;s SSL/TLS library (Schannel)&lt;/a&gt; allowing remote code
execution.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/POODLE&#34;&gt;POODLE&lt;/a&gt;, a flaw in
the SSLv3 protocol that an attacker can leverage on many connections by
forcing a protocol downgrade, or relying on certain flaws in TLS
implementations.&lt;/li&gt;
&lt;li&gt;Attackers&#39; increasing boldness in targeting networks for financial gain
(&lt;a href=&#34;https://corporate.target.com/about/shopping-experience/payment-card-issue-FAQ&#34;&gt;Target&lt;/a&gt;,
&lt;a href=&#34;http://krebsonsecurity.com/tag/home-depot-breach/&#34;&gt;Home Depot&lt;/a&gt;)
or cybervandalism
(&lt;a href=&#34;http://en.wikipedia.org/wiki/Sony_Pictures_Entertainment_hack&#34;&gt;Sony Pictures&lt;/a&gt;),
resulting in hundreds of millions &amp;mdash; or perhaps even billions
&amp;mdash; of dollars in damages.&lt;/li&gt;
&lt;li&gt;A rising awareness of state-sponsored attacks, from actors such as
the NSA
(&lt;a href=&#34;http://en.wikipedia.org/wiki/Regin_%28malware%29&#34;&gt;Regin malware&lt;/a&gt;),
the UK&#39;s GCHQ
(&lt;a href=&#34;http://www.spiegel.de/international/europe/british-spy-agency-gchq-hacked-belgian-telecoms-firm-a-923406.html&#34;&gt;Belgacom attack&lt;/a&gt;),
and North Korea (alleged perpetrator of the Sony Pictures attack).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
How did our infrastructure become so fragile?  How did the miracles of
technology turn against us?  Who is responsible for this?
Regrettably, my fellow software engineers and I are largely responsible.
Together, we have created this frightening new world where people&#39;s
property, finances, and privacy are at risk.
&lt;/p&gt;

&lt;blockquote&gt;
&amp;#8220;If builders built buildings the way programmers wrote programs, then
the first woodpecker that came along would destroy civilization.&amp;#8221; &amp;mdash;
Gerald Weinberg
&lt;/blockquote&gt;

&lt;p&gt;
Weinberg&#39;s famous quote about software quality points out a lack of
rigor that can be seen in the software industry for decades.  In the
1970&#39;s and 1980&#39;s, the nascent Internet was a more civilized place,
similar to a small town where people felt comfortable leaving their
front doors unlocked.  Accordingly, we built software with little
consideration of security.  Unencrypted communication protocols like
&lt;a href=&#34;http://tools.ietf.org/html/rfc15&#34;&gt;telnet&lt;/a&gt; would happily
share your passwords with any eavesdropper, and lax security in other
network services would eventually expose
&lt;a href=&#34;http://en.wikipedia.org/wiki/Morris_worm&#34;&gt;unexpected attack modes&lt;/a&gt;
that were perhaps obvious only in hindsight.  In the 1990&#39;s and 2000&#39;s,
we wised up with better encryption, authentication, authorization, and
recognition of security as an explicit engineering goal.  (As far as I
can tell, the first RFC with a dedicated &amp;#8220;Security Considerations&amp;#8221;
section was
&lt;a href=&#34;https://tools.ietf.org/html/rfc1060&#34;&gt;RFC 1060&lt;/a&gt; from March
1990.)
&lt;/p&gt;

&lt;p&gt;
However, although we managed to lock the front door, we left our systems
vulnerable in many other ways.  Memory safety errors, unexpected
consequences emerging from complexity, and numerous mundane code
correctness issues provided attackers with a seemingly endless toolkit
for compromising systems.
&lt;/p&gt;

&lt;p&gt;
Many other engineering disciplines have the benefit of hundreds or
thousands of years of accumulated wisdom that have resulted in highly
refined tools and methods.  Designing bridges or buildings, for example,
is a well-understood process.  We&#39;ve only been developing software for
about 60 years, and only been developing software at a large scale for
maybe 30-40 years.  Our field is very much still in its infancy: our
tools are sorely lacking, our methods tend to be ad-hoc, and lack of
experience leads us to be overconfident in our ability to produce
correct code.  Our products often fail to provide the basic functions
expected by the user, much less withstand attacks by a thinking,
creative adversary.  It pains me that we&#39;ve let down our employers,
customers, and users by producing such flawed products.
&lt;/p&gt;

&lt;p&gt;
Software development must reinvented.  We need better tools and methods
to build more reliable software, and an environment that values security
and rewards engineers and companies for producing such software.  These
things are easier said than done, and I don&#39;t have all the solutions.  I
do know that it&#39;s time to start working on solutions.  The threat level
is not going down any time soon.  In fact, I expect it to rise with our
increased reliance on software systems and as recent high-profile
attacks show the world&#39;s miscreants just how vulnerable we are.
&lt;/p&gt;

&lt;p&gt;
The woodpeckers are coming.
&lt;/p&gt;

&lt;h2&gt;Limitations of defensive technology&lt;/h2&gt;

&lt;p&gt;
The industry&#39;s solution is to double down on defensive technology &amp;mdash;
malware scanners, firewalls, intrusion detection appliances, and similar
systems.  While these play an important role, it is increasingly
difficult for defensive systems to shoulder the entire burden of
security while an army of software engineers continues to supply a
never-ending fountain of vulnerabilities.  Firewalls become less
effective as more software integrates firewall-bypassing communication
channels with cloud services, attackers seek to exploit flaws in such
software, and malware is distributed out-of-band.  Malware scanners
especially face tough challenges as fully &lt;a
href=&#34;http://en.wikipedia.org/wiki/Metamorphic_code&#34;&gt;metamorphic&lt;/a&gt;
viruses are already extremely difficult to detect, and likely have a lot
more opportunities for improvement than the scanners have options for
improving detection.
&lt;/p&gt;

&lt;p&gt;
Ultimately, software engineers are able to create security problems much
faster than producers of defensive products can figure out ways to
contain them.  We must stop thinking of security in terms of band-aids,
and address the source of the problem by developing software that is
secure by design.
&lt;/p&gt;

&lt;h2&gt;Attacking attack vectors with better tools and methods&lt;/h2&gt;

&lt;p&gt;
We can broadly divide the attack universe into two categories:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Software engineering attack vectors.  This includes programming issues
such as memory safety and code correctness, and system design issues
dealing with authentication schemes, cryptosystems, protocols,
complexity management, and the user experience.
&lt;/li&gt;
&lt;li&gt;
Other attack vectors found in system administration, configuration,
networking, wiring, physical side channel emissions, passwords, social
engineering, operational security, and physical security.
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
As a software engineer interested in improving software engineering, I&#39;m
focused on the former category.  Examining a few of the recent high-profile
vulnerabilities is useful for thinking about how we can approach certain
attack vector categories.
&lt;/p&gt;

&lt;h3&gt;Heartbleed and memory safety&lt;/h3&gt;

&lt;blockquote&gt;
&amp;#8220;Whenever I go to debian.org and look at the latest security fixes, the
vast majority of them involve memory safety issues, which only appear in
unsafe languages such as C and C++.&amp;#8221;
&lt;br /&gt;
&amp;mdash; &lt;a href=&#34;http://security.stackexchange.com/questions/44102/why-are-security-crucial-software-written-in-unsafe-languages&#34;&gt;user54609&lt;/a&gt;, Information Security Stack Exchange
&lt;/blockquote&gt;

&lt;p&gt;
Memory safety issues are behind a huge chunk of vulnerabilities, such as
OpenSSL&#39;s Heartbleed.  Much security-sensitive code is written in
low-level languages because we seek performance, minimal memory
footprint, minimal dependencies, interoperability, and sometimes
fine-grain control over execution.  This is especially true for
cryptography, where we&#39;d like the CPU overhead to be as close to zero as
possible, and avoid potential timing attacks that could arise from
high-level language execution.  However, developing complex systems in C
and C++ can require a superhuman level of attention to detail to avoid
memory errors, and even the most capable programmers seem to let such
errors slip through on occasion.  Although techniques exist to help
minimize such errors (e.g. C++ smart pointers), it may not be possible
to develop a large, complex C/C++ program with a high assurance of
correct memory usage.
&lt;/p&gt;

&lt;p&gt;
Fortunately, there has been much interest lately in developing new
low-level languages with memory safety assurances.  My favorite of these
is currently &lt;a href=&#34;http://www.rust-lang.org/&#34;&gt;Rust&lt;/a&gt;, which
promises zero-cost memory safety by requiring that the programmer adhere
to a certain memory management discipline.  Rust is the most promising
step toward reinventing software that I see today.
If our critical low-level infrastructure was written in Rust instead of
C/C++, we would be far more secure.  Heartbleed would not have happened
if OpenSSL was written in Rust.
&lt;/p&gt;

&lt;p&gt;
Rust is still a work in progress, can be difficult to use, and
even a fully mature Rust may not be the final solution.  Other new
languages also have merit.  The &lt;a href=&#34;https://golang.org/&#34;&gt;Go
programming language&lt;/a&gt; looks promising and is quite a bit more mature
than Rust.  However, Go&#39;s mandatory garbage collection may exclude it
from certain applications, such as operating system kernels, real-time
tasks, or possibly cryptography.  (It&#39;s not clear to me if garbage
collection can contribute to timing side channels in cipher
implementations.  I&#39;d love to see some research on this.)
&lt;/p&gt;

&lt;p&gt;
When it comes to memory safety bugs, the path ahead is refreshingly
clear: new high-performance, low-level programming languages that
prevent these bugs from happening.  Unfortunately, general solutions for
other classes of bugs remain murky.
&lt;/p&gt;

&lt;h3&gt;Shellshock and emergent vulnerabilities&lt;/h3&gt;

&lt;blockquote&gt;
&#34;So who&#39;s to blame? Everybody and nobody. The system is so complex that
unwanted behaviours like these emerge by themselves, as a result of the
way the components are connected and interact together.  There is no
single master architect that could&#39;ve anticipated and guarded against
this.&#34;
&lt;br /&gt;
&amp;mdash; &lt;a href=&#34;http://blog.senko.net/shellshock&#34;&gt;Senko Rasic on Shellshock&lt;/a&gt;
&lt;/blockquote&gt;

&lt;p&gt;
The Shellshock vulnerability in Bash is a great example for reminding us
that some threats can be created even with the most logically consistent
and memory-safe code.  Writing Bash in a rigorous language such as Rust
would not have prevented Shellshock from happening, nor would any amount
of static analysis have revealed the problem.  Shellshock arises from a
feature added to Bash in 1992 for passing shell functions to child Bash
processes using environment variables.  The feature seems to be
implemented by passing the environment variable&#39;s value directly to
Bash&#39;s interpreter, as commands provided after the close of the function
definition will be parsed and executed immediately.  This probably
seemed like a reasonable feature in 1992, but it became a devastating
vulnerability when Bash became the glue tying network services to
scripts (e.g. web servers to CGI scripts, or DHCP clients to hook
scripts), and environment variables could suddenly contain hostile
payloads, thus providing remote code execution to external parties.
&lt;/p&gt;

&lt;p&gt;
It would have been nice if the troublesome feature halted interpretation
at the end of the function definition, but even provisioning functions
from environment variables was something that network service developers
could not have anticipated.  Indeed, they probably didn&#39;t anticipate the
use of Bash at all &amp;mdash; they were merely passing data to a child process
in a generic fashion, and the use of Bash was often simply a result of
how the system administrator or the distribution maintainer connected
the pieces.  Thus, Shellshock falls into an elusive category of &lt;a
href=&#34;http://blog.senko.net/shellshock&#34;&gt;emergent vulnerabilities&lt;/a&gt;
that can arise in complex systems.
&lt;/p&gt;

&lt;p&gt;
This class of vulnerability is particularly disturbing since most
software is built around the idea of reusable modules of code, many of
which may be supplied by external vendors, and connected in a vast
number of combinations.  We need engineering methods for dealing with
this complexity, but I&#39;m not sure exactly what these would be.  Perhaps
interface definitions between software components could make formal
guarantees about how the passed data will be used.
&lt;/p&gt;

&lt;h3&gt;Apple&#39;s &amp;#8220;&lt;tt&gt;goto fail&lt;/tt&gt;&amp;#8221; bug and code correctness&lt;/h3&gt;

&lt;p&gt;
Apple&#39;s &lt;a
href=&#34;http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-1266&#34;&gt;&lt;tt&gt;goto
fail&lt;/tt&gt;&lt;/a&gt; bug, revealed in February 2014, prevented signature
verification from happening properly in TLS handshakes, thus allowing
man-in-the-middle attacks.  The cause of the bug was a minor typo in the
source code which led to unintended behavior.  The program was incorrect
&amp;mdash; its behavior did not match its specification.  Incorrect code can be
produced by even the very best programmers, since these programmers are
human beings and will occasionally make human mistakes.
&lt;/p&gt;

&lt;p&gt;
Mike Bland believes that the &amp;#8220;&lt;tt&gt;goto fail&lt;/tt&gt;&amp;#8221; bug could have been
avoided by &lt;a
href=&#34;http://martinfowler.com/articles/testing-culture.html&#34;&gt;promoting a
unit test culture&lt;/a&gt;, and Adam Langley &lt;a
href=&#34;https://www.imperialviolet.org/2014/02/22/applebug.html&#34;&gt;
suggests code reviews&lt;/a&gt;.  These are both great ideas, especially for
such critical code.  However, I wonder if there are ways we can avoid
creating these errors to begin with, instead of hoping to catch them
later in a mop-up phase.  Would use of functional languages like &lt;a
href=&#34;https://www.haskell.org/&#34;&gt;Haskell&lt;/a&gt; help us better express our
intentions?  Could
&lt;a href=&#34;http://en.wikipedia.org/wiki/Formal_methods&#34;&gt;formal methods&lt;/a&gt;
and
&lt;a href=&#34;http://en.wikipedia.org/wiki/Formal_specification&#34;&gt;formal
specifications&lt;/a&gt;
be useful for catching such implementation errors?
&lt;/p&gt;

&lt;h3&gt;POODLE and the trouble with cryptographic protocols and implementations&lt;/h3&gt;

&lt;p&gt;
The &lt;a href=&#34;http://en.wikipedia.org/wiki/POODLE&#34;&gt;POODLE&lt;/a&gt; attack
revealed in September 2014 allows attackers to target secure connections
protected with correct SSL 3.0 implementations, or TLS implementations
with certain coding errors.  (Although SSL 3.0 is 18 years old and
seldom used in normal operation, this is still quite concerning as an
attacker can use a forced downgrade attack to cause an SSL 3.0 session
to be negotiated.)  This reminds us that bugs can exist in protocols
themselves, and cryptography can be enormously difficult to implement
correctly.  It&#39;s not good enough for cryptography implementations to
properly encode and decode &amp;mdash; to be secure, they must be mindful to a
long list of small details involving parsing, padding, execution time
(to avoid timing side channels), proper use of random number generators,
and many more.
&lt;/p&gt;

&lt;p&gt;
The best bits of advice I&#39;ve heard about implementing cryptography are:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Practice extreme humility &amp;mdash; overconfidence is the enemy of
security.  Know that no matter how good you are, your fresh
cryptographic code is likely to have subtle problems.&lt;/li&gt;
&lt;li&gt;Reuse existing cryptographic code modules whenever possible,
preferably modules that have been audited, rigorously tested, and
battle-hardened through their production use.  As full of holes as
OpenSSL is thought to be, it is probably more secure than whatever you
would write to replace it.  Better yet, consider opinionated toolkits
such as &lt;a href=&#34;http://doc.libsodium.org/&#34;&gt;the Sodium crypto
library&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;Seek expert assistance from professional cryptographers and security
experts, when possible.  There are people out there who have made it
their life&#39;s work to study cryptography and its practical use, although
they are probably not cheap.&lt;/li&gt;
&lt;li&gt;Commission third-party security audits.  When we programmers look at
the same body of code for weeks at a time, we often lose the ability to
view it critically.  Fresh eyes can be invaluable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
The best engineering improvement I can think of is the use of
domain-specific languages to specify protocols and algorithms, as this
may help avoid the pitfalls of implementing cryptography in general
purpose languages.  I&#39;m encouraged by projects such as Nick Mathewson&#39;s
&lt;a
href=&#34;https://lists.torproject.org/pipermail/tor-dev/2014-October/007580.html&#34;&gt;Trunnel&lt;/a&gt;,
a binary parser generator for protocols.
&lt;/p&gt;

&lt;h2&gt;Economics of secure software&lt;/h2&gt;

&lt;blockquote&gt;
&amp;#8220;It&#39;s a valid business decision to accept the risk [of a security breach]...
I will not invest $10 million to avoid a possible $1 million loss.&amp;#8221;
&lt;br /&gt;
&amp;mdash; Jason Spaltro, senior vice president of information security,
Sony Pictures, in a &lt;a href=&#34;http://www.cio.com/article/2439324/risk-management/your-guide-to-good-enough-compliance.html&#34;&gt;2007 interview with CIO&lt;/a&gt;.
&lt;/blockquote&gt;

&lt;p&gt;
From individual consumers to the largest companies, security often seems to
be valued rather low.
Mr. Spaltro&#39;s unfortunate cost-benefit analysis has been mentioned often
in the days since the devastating Sony Pictures attack was made public.
However, I doubt his thinking was too far out of line with others at
the time.  In most organizations, information technology is a cost
center that does not directly contribute to the bottom line, so it&#39;s
understandable that companies would seek to minimize its expense.  There
is probably considerable temptation to underestimate the cost of
breaches.  This is regrettable, as even with improved engineering tools
and methods, the financial investment needed to develop, audit, and
deploy improved software may be quite large.  I suspect companies such
as Sony, Target, and Home Depot now have a better understanding of risks
and may be willing to invest more money into security.  Hopefully some
of their security budget will include software better engineered for
security, whether supplied by external vendors or developed in-house.
In the end, it may take hundreds of billions or even trillions of
dollars to rebuild our software foundations.
&lt;/p&gt;

&lt;p&gt;
One great puzzle is figuring out how to fund the development and
auditing of open-source software.  Much of the technology we use every
day relies on various open-source software modules under the hood, and
our security relies on these modules being reliable.  Additionally, the
inherent auditability of open-source software makes it important for
resisting attempts by governments to weaken security by coercing
companies to include intentional flaws in their software.  Of course,
simply being open-source does not automatically make software more
trustworthy.  Being open-source is &lt;em&gt;necessary but not
sufficient&lt;/em&gt;.  There is not an army of bored software engineers
browsing through GitHub projects looking for flaws because they think
it&#39;s a fun way to spend a Saturday night.  With the right funding,
though, we can pay qualified experts to conduct thorough audits.
&lt;/p&gt;

&lt;p&gt;
I&#39;m highly encouraged by the efforts of several groups to help fund
audits and other security investigations, whether their motivations
arise from their reliance on the security of the targeted software,
positive public relations, self-promotion, or something else entirely.  For
example, the &lt;a href=&#34;https://opencryptoaudit.org/&#34;&gt;Open Crypto Audit
Project&lt;/a&gt; is funding the necessary auditing of critical open-source
projects.  Although their visible efforts to date have been limited to a
crowdfunded audit of TrueCrypt, Kenneth White spoke at last summer&#39;s
DEFCON about their intention to begin an audit of OpenSSL funded by the
&lt;a
href=&#34;http://www.linuxfoundation.org/programs/core-infrastructure-initiative&#34;&gt;Linux
Foundation&#39;s Core Infrastructure Initiative&lt;/a&gt;, which itself is funded
by a long list of big names such as Google, Intel, Microsoft, and
Amazon.  Such investment from stakeholders to fund security audits seems
like a very reasonable approach.  Likewise, &lt;a
href=&#34;http://googleonlinesecurity.blogspot.com/2014/07/announcing-project-zero.html&#34;&gt;Google&#39;s
Project Zero&lt;/a&gt; is a team of security researchers tasked with improving
the security of all commonly used software.  Even some security
consultancies are finding the time for pro bono investigations, such as
with the &lt;a href=&#34;https://cryptoservices.github.io/&#34;&gt;Cryptography
Services&lt;/a&gt; effort.
&lt;/p&gt;

&lt;p&gt;
I&#39;m optimistic about the improvement of many classes of software being
driven by increased demand from businesses.  Selling end users on the
idea of paying for security may be a much tougher challenge in a market
dominated by free advertiser-sponsored software and services (e.g.
mobile apps, popular web sites, etc.).  We have much more work ahead of
us to construct a workable value proposition for this market.
&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;
Looking at the current state of software security and the harm of recent
attacks can be a bit of a downer, but I remain optimistic that we can
fix many of the problems with better engineering and better funding.
What can we do to push the state of software engineering forward and
create a more secure world?
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Study new programming languages built for better memory safety
without sacrificing high performance.  Think about which critical
software modules might be best suited for implementation in these
languages, and which can be implemented in high-level languages.
If you must use C++, learn the
&lt;a href=&#34;http://en.cppreference.com/w/cpp/memory&#34;&gt;latest techniques for
helping improve memory safety&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;Develop new abstractions that may improve software reliability, such
as generators for protocol handlers and cryptography algorithms.&lt;/li&gt;
&lt;li&gt;Think about engineering methods that may improve code
correctness, and how they can be applied to existing software
development processes.&lt;/li&gt;
&lt;li&gt;Develop funding mechanisms and more compelling end-user value
propositions so that software engineers working on better security can
be rewarded by those who value it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
I&#39;d love to hear about any ideas you may have about making the world&#39;s
software infrastructure more resilient to attack.
&lt;/p&gt;
</description>
        </item>
    
        <item>
          <title>Battery cost of periodic mobile network use</title>
          <link>https://cafbit.com/post/battery_cost_of_periodic_mobile/</link>
          <pubDate>Mon, 06 Oct 2014 20:53:47 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/battery_cost_of_periodic_mobile/</guid>
          <description>&lt;p&gt;
As the consumer electronics revolution brings more and more of the
digital world to handheld devices, the chief constraint developers often
face is not bandwidth or CPU cycles, but rather battery life.  Since
many next-generation applications require creative use of the network, I
decided to run a few tests to discover the true battery cost of network
use in certain scenarios.
&lt;/p&gt;

&lt;p&gt;
I have an interest in mesh overlay networks, and I&#39;m curious about the
cost of mesh maintenance on power-constrained devices.  Therefore, these tests
explore the use of relatively small network transactions performed at
regular intervals.  Mobile devices are known to be optimized for
aggregated time-adjacent traffic, with the radio wake-up cost leading to
a low ROI for small (e.g. one IP packet) transmissions.  This could
unfortunately be bad news for mesh maintenance, where lots of small
transmissions are spread out in time.
&lt;/p&gt;

&lt;p&gt;
Ilya Grigorik&#39;s
&lt;em&gt;&lt;a href=&#34;http://shop.oreilly.com/product/0636920028048.do&#34;&gt;High
Performance Browser Networking&lt;/a&gt;&lt;/em&gt;
(O&#39;Reilly Media, 2013) goes into detail about these issues in
Chapter 7
&lt;a href=&#34;http://chimera.labs.oreilly.com/books/1230000000545/ch07.html&#34;&gt;
&#34;Mobile Networks&#34;&lt;/a&gt;
and Chapter 8
&lt;a href=&#34;http://chimera.labs.oreilly.com/books/1230000000545/ch08.html&#34;&gt;
&#34;Optimizing for Mobile Networks&#34;&lt;/a&gt;.
Some key insights from this work include:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&#34;The &#34;energy tails&#34; generated by the timer-driven state transitions make
periodic transfers a very inefficient network access pattern on mobile
networks.&#34;&lt;/li&gt;
&lt;li&gt;
&#34;Radio use has a nonlinear energy profile with respect to data
transferred.&#34;&lt;/li&gt;
&lt;li&gt;&#34;Intermittent network access is a performance anti-pattern on mobile
networks...&#34;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Test methodology&lt;/h2&gt;

&lt;p&gt;
Earlier this year when I was switching carriers, I found myself with a
spare Android handset with LTE service enabled.  Seizing the opportunity
of having an activated handset that&#39;s not saddled with my usual array of
chatty apps (mail, Twitter, etc.), I ran a series of tests measuring
battery drain in various controlled network conditions.
&lt;/p&gt;

&lt;p&gt;
The handset under test was a Samsung Galaxy Nexus running Android 4.3,
equipped with the factory supplied 1850mAh battery.  The network
connection was provided by Sprint&#39;s LTE network.  To reduce the amount
of unintentional background network traffic, the device was reset to
factory defaults and not associated with any Google account.
&lt;/p&gt;

&lt;p&gt;
I developed an app to perform network traffic at a specified interval
and record the battery level and network counters each minute.  This app
sends a 1400-byte UDP packet as an echo request to a cloud server, where
a small Python script verifies the authenticity of the request and
returns a 1400-byte UDP echo response packet.  In this fashion,
network traffic should be roughly balanced between upload and download,
minus any occasional packet loss.
&lt;/p&gt;

&lt;p&gt;
To judge the overall battery usage for an individual test with a
specific network transaction frequency, I measured the time elapsed
while the battery drained from 90% to 30%.  (Battery usage was seen to
have some aberrations above 90% and below 30%, so such data was
discarded for the purpose of calculating drainage times.)
&lt;/p&gt;

&lt;h2&gt;Caveats&lt;/h2&gt;

&lt;p&gt;
This is not a fully controlled laboratory test or representative of a
broad range of devices and networks, but rather a &#34;best-effort only&#34;
test using the equipment at hand.  Thus, it&#39;s important to keep in mind
a number of caveats:
&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;The LTE signal strength is not guaranteed to be constant
    throughout the test.  I tried to minimize the variation by always
    performing tests with the handset in the same physical location and
    orientation, but there are many factors out of my control.  A lower
    signal strength requires the radio to transmit with higher power to
    reach the tower, so this could add noise to the data.&lt;/li&gt;
    &lt;li&gt;LTE is something of a black box to me, so any peculiarities of
    the physical and link layers are not taken into account.  For
    example, are there conditions that may prompt the connection to
    shift to a different band with different transmit power
    requirements?&lt;/li&gt;
    &lt;li&gt;Other wireless providers may use LTE in different frequencies or
    configurations which may affect the battery usage in different
    ways.&lt;/li&gt;
    &lt;li&gt;Android&#39;s background network traffic could not be 100% silenced,
    and I did not go to extraordinary lengths to track down every last
    built-in app that occasionally uses the network.  However, this
    unintentional traffic should be fairly negligible.&lt;/li&gt;
    &lt;li&gt;This test only considers one specific mobile device with one
    operating system.  Other models will have radios with different
    power usage characteristics.&lt;/li&gt;
    &lt;li&gt;Wi-Fi use is not tested.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;Results&lt;/h2&gt;

&lt;p&gt;&lt;img src=&#34;https://cafbit.com/resource/batterycost/ctl.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://cafbit.com/resource/batterycost/512.png&#34;&gt; &lt;img src=&#34;https://cafbit.com/resource/batterycost/256.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://cafbit.com/resource/batterycost/128.png&#34;&gt; &lt;img src=&#34;https://cafbit.com/resource/batterycost/064.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://cafbit.com/resource/batterycost/032.png&#34;&gt; &lt;img src=&#34;https://cafbit.com/resource/batterycost/016.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://cafbit.com/resource/batterycost/008.png&#34;&gt; &lt;img src=&#34;https://cafbit.com/resource/batterycost/004.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://cafbit.com/resource/batterycost/002.png&#34;&gt; &lt;img src=&#34;https://cafbit.com/resource/batterycost/001.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://cafbit.com/resource/batterycost/drainage.png&#34;&gt;&lt;/p&gt;
&lt;p&gt;
Note that the echo frequency above is in &lt;em&gt;milli&lt;/em&gt;hertz (mHz), not
&lt;em&gt;mega&lt;/em&gt;hertz (MHz) &amp;mdash; 1000mHz is 1 echo request/response per second.
&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;
One surprising result was the battery longevity in the control test.
While most of us have grown accustomed to charging our mobile devices
every day, it turns out that with minimal network activity, they can
last quite a long time indeed.  In this case, the Galaxy Nexus lasts
almost three days while associated with an LTE tower.
&lt;/p&gt;

&lt;p&gt;
As expected, the relationship between periodic network use and battery
drainage is non-linear.  For example, doubling the transaction frequency
&amp;mdash; say, from 128-second intervals to 64-second intervals &amp;mdash;
doesn&#39;t halve the 90-30% drain time; it only lowers it by 32%.
Additionally, there seems to be a leveling out around 8-second (and
shorter) intervals.  Perhaps certain radio components never power down
with such frequent transmissions.
&lt;/p&gt;

&lt;p&gt;
Overall, the situation looks pretty grim for mobile devices being full,
continuous participants in mesh overlay networks.  The modest bandwidth
needs of such applications are overshadowed by the battery impact of
using the network in little sips throughout the day.  Perhaps a system
where all participants agreed to a synchronized schedule for mesh
maintenance activities could mitigate the problem, but the benefits are
not clear when combined with real-time mesh events instigated by remote
users (say, a Kademlia node lookup).
&lt;/p&gt;

&lt;p&gt;
It might be interesting to evaluate the impact of periodic network use
with Wi-Fi, or investigate the techniques used by platform push systems
such as &lt;a href=&#34;https://developer.android.com/google/gcm/index.html&#34;&gt;Google
Cloud Messaging&lt;/a&gt; and the
&lt;a href=&#34;https://developer.apple.com/library/IOs/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html&#34;&gt;
Apple Push Notification&lt;/a&gt; service.
&lt;/p&gt;
</description>
        </item>
    
        <item>
          <title>Highlights of DEFCON 22</title>
          <link>https://cafbit.com/post/highlights_of_defcon_22/</link>
          <pubDate>Thu, 14 Aug 2014 01:29:31 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/highlights_of_defcon_22/</guid>
          <description>&lt;p&gt;
The twenty-second DEFCON took over Las Vegas last week, and brought many interesting and notable speakers.  I took a few notes from the talks that stood out to me, and I&#39;m passing them along here.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Paul_Vixie&#34;&gt;Paul Vixie&lt;/a&gt;, Internet pioneer and DNS expert.&lt;/b&gt;  Vixie spoke about his &lt;a href=&#34;https://www.dnsdb.info/&#34;&gt;DNSDB&lt;/a&gt; project for accumulating global DNS resource records in a passive fashion, and making this information available to researchers and security product vendors.  He also spoke about his &lt;a href=&#34;http://www.circleid.com/posts/20120103_dns_firewalls_in_action_rpz_vs_spam/&#34;&gt;DNS firewall&lt;/a&gt; for shielding users from malicious throwaway domain names.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;a href=&#34;http://en.wikipedia.org/wiki/Phil_Zimmermann&#34;&gt;Phil Zimmerman&lt;/a&gt;, creator of &lt;a href=&#34;http://en.wikipedia.org/wiki/Pretty_Good_Privacy&#34;&gt;PGP&lt;/a&gt; and president of &lt;a href=&#34;https://silentcircle.com/&#34;&gt;Silent Circle&lt;/a&gt;.&lt;/b&gt;  Zimmerman spoke about wiretap overcompliance in the telecommunications industry, trust in cryptographic techniques, and his new endeavors at Silent Circle.  Reading about Zimmerman&#39;s PGP efforts and the resulting drama (&lt;em&gt;&lt;a href=&#34;http://shop.oreilly.com/product/9781565920989.do&#34;&gt;PGP: Pretty Good Privacy&lt;/a&gt;&lt;/em&gt;, Simson Garfinkel) is what got me interested in cryptography many years ago, so it was great to see a living legend on the stage.  I did take issues with a few of his comments, though.  When asked about trusting binary executables, Zimmerman mentioned the problem of distributing a binary which is identical to one that might be produced from source, due to differences in timestamps &amp;mdash; and failed to discuss recent progress in &lt;a href=&#34;https://wiki.debian.org/ReproducibleBuilds&#34;&gt;reproducible build&lt;/a&gt; techniques which are meant to solve that problem.  He also painted a somewhat rosy picture of the legislative attitude towards cryptography and privacy: we won the Crypto Wars in the 1990&#39;s, and cryptographic freedom can&#39;t be rolled back again now that everyone relies on it.  This does not seem to be the case &amp;mdash; last year, Congress and the administration was pushing a proposal which would &lt;a href=&#34;http://www.wired.com/2013/05/the-fbis-plan-for-a-wiretap-ready-internet-is-misdirected-shortsighted-and-ridiculous/&#34;&gt;effectively outlaw peer-to-peer communication systems&lt;/a&gt; that might be problematic to wiretap.  (Thankfully, the Snowden revelations made the proposal politically toxic for now, and it has been shelved.)
&lt;p&gt;

&lt;p&gt;
&lt;b&gt;&lt;a href=&#34;https://twitter.com/kennwhite&#34;&gt;Kenneth White&lt;/a&gt;, security researcher.&lt;/b&gt;  White spoke about the &lt;a href=&#34;https://opencryptoaudit.org/&#34;&gt;Open Crypto Audit&lt;/a&gt; project which he launched along with cryptographer &lt;a href=&#34;http://blog.cryptographyengineering.com/&#34;&gt;Matthew Green&lt;/a&gt;, and the drama caused by their first audit subject, TrueCrypt, being &lt;a href=&#34;http://www.darkreading.com/endpoint/the-mystery-of-the-truecrypt-encryption-software-shutdown-/d/d-id/1269323&#34;&gt;suddenly discontinued under mysterious circumstances&lt;/a&gt;.  I&#39;ve followed the progress of the Open Crypto Audit project and the ongoing news about the TrueCrypt disappearance, so there wasn&#39;t much in the talk that was new to me.  It was interesting to hear that some of the biggest challenges of Open Crypt Audit were the community aspects of audit fundraising.  White reported that they will finish the TrueCrypt audit in spite of the shutdown, and then move on to OpenSSL.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;a href=&#34;http://dankaminsky.com/&#34;&gt;Dan Kaminsky&lt;/a&gt;, security researcher.&lt;/b&gt;  Kaminsky scored a coveted two-hour slot in the Penn and Teller theater, which he fully used to discuss a variety of topics:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Secure random by default.&lt;/b&gt;  Kaminsky argued that most vulnerabilities resulting from random number generation are not due to exotic attacks on complex algorithms, but rather gross missteps in the use and generation of randomness.  For instance, some software has been observed to only effectively use 32 bits of entropy, while others employ the use of &lt;a href=&#34;http://en.wikipedia.org/wiki/Linear_feedback_shift_register&#34;&gt;linear feedback shift registers (LFSRs)&lt;/a&gt; in spite of their easy cryptanalysis.  Kaminsky proposes a new Liburandy library which wraps &lt;tt&gt;/dev/urandom&lt;/tt&gt; when appropriate.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Storybits.&lt;/b&gt;  Kaminsky invited Ryan Castellucci onto the stage to demonstrate Storybits 0.1, a new cryptomnemonic scheme for people to remember binary strings such as keys, fingerprints, secrets, etc.  The system encodes the data as adjective-noun-verb tuples to make the data easier to remember, and provide error correction by way of spellcheck auto-correct.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Memory hardening.&lt;/b&gt;  Convinced that improper memory usage is a major cause of vulnerabilities, Kaminsky outlined several strategies for memory-hardening applications.  These include use of a typed heap (as Google does in Chrome), the use of nondeterministic freeing (as Microsoft does in Internet Explorer), and a novel approach called IronHeap where 64-bit virtual memory addresses are simply never freed (although pages may be returned for MMU reuse).  He also announced the formation of a team to memory-harden Firefox, to provide added security for the Tor Browser Bundle.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Distributed Denial of Service (DDoS) mitigation.&lt;/b&gt;  Kaminsky considers the rise of DDoS attacks using techniques such as datagram amplification to be an existential threat to the Internet.  He proposes a new scheme of sending tracer packets within data flows to indicate when source address spoofing may be happening.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;NSA.&lt;/b&gt;  Kaminsky is concerned that the NSA backlash may lead to a balkanization of the Internet, as various nations opt to develop their own internal systems for core Internet services.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Apple bug bounties.&lt;/b&gt;  Finally, Kaminsky is quite happy that Apple is offering bug bounties relating to Safari autoredirection.
&lt;/ul&gt;
&lt;p&gt;Kaminsky&#39;s &lt;a href=&#34;http://www.slideshare.net/dakami/yet-another-dan-kaminsky-talk-black-ops-2014&#34;&gt;slides are available&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;a href=&#34;https://twitter.com/kingladar&#34;&gt;Ladar Levison&lt;/a&gt;, founder of &lt;a href=&#34;http://en.wikipedia.org/wiki/Lavabit&#34;&gt;Lavabit&lt;/a&gt;.&lt;/b&gt;  Levison spoke about his proposed &lt;a href=&#34;https://www.darkmail.info/&#34;&gt;Dark Mail Alliance&lt;/a&gt;, a new electronic mail system designed to preserve the privacy of users.  He began by announcing a new name for the project: DIME, the Dark Internet Mail Environment.  I was a bit disappointed in the new name &amp;mdash; &#34;Dark&#34; can have a sinister connotation for some people, and privacy preserving technologies should be marketed to the public with positive names reflecting the true value they provide.  He should have renamed the project TIME, the &lt;em&gt;Trustworthy&lt;/em&gt; Internet Mail Environment.  Levison outlined the basic components of the system, including a server called Magma and a modified Thunderbird client called Volcano.  DIME unfortunately does not provide forward secrecy for messages, although Levison pointed out that there was forward secrecy at the TLS1.2 line level.  There was also talk of a pseudo-onion scheme to shield metadata and provide some small measure of anonymity, but it wasn&#39;t clear to me how this was implemented.
&lt;/p&gt;

&lt;p&gt;
&lt;b&gt;&lt;a href=&#34;https://adamcaudill.com/&#34;&gt;Adam Caudill&lt;/a&gt;, software developer and security researcher.&lt;/b&gt;
In DEFCON&#39;s new Crypto Village, Caudill proposed a new secure electronic mail system called &lt;a href=&#34;http://smimp.org/&#34;&gt;Simple Messaging and Identity Management Protocol&lt;/a&gt; (SMIMP).  This scheme shares some of the same goals as Levison&#39;s DIME, but provides an alternative design intended to be developed in the open among the greater Internet engineering community.  The most interesting thing to me was a Hashcash-like proof-of-work requirement for reducing spam.
&lt;/p&gt;
</description>
        </item>
    
        <item>
          <title>Recent Android &#34;Package file is invalid&#34; errors</title>
          <link>https://cafbit.com/post/android_package_file_is_invalid/</link>
          <pubDate>Sun, 11 Aug 2013 05:00:04 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/android_package_file_is_invalid/</guid>
          <description>&lt;p&gt;
In the past day or so, I&#39;ve been noticing these &#34;Package file is invalid&#34; errors on my Android devices while trying to upgrade or install certain packages from the Play Store.  A bit of searching revealed that many others are having this problem, and various
&lt;a href=&#34;http://www.droid-life.com/2013/08/08/play-store-update-to-4-3-10-causing-package-file-is-invalid-error-for-many-during-app-updates/&#34;&gt;home remedies&lt;/a&gt;
abound for trying to fix it, such as clearing the Play Store&#39;s app cache.  Unfortunately, while these remedies may have worked for past problems that led to this error message being displayed, they are useless when trying to fix the issue people are experiencing this weekend.
&lt;/p&gt;

&lt;p&gt;
I decided to do a bit of digging, and I found that Google&#39;s web servers are actually sending corrupted packages to the Play Store app.  Therefore, no amount of tweaking your device will fix the problem.  (Unless such tweaking happens to result in pulling packages from a different web server that doesn&#39;t have corrupted files, I suppose.)
&lt;/p&gt;

&lt;p&gt;
&lt;em&gt;UPDATE 2013-08-12: It appears that this problem is isolated to one or more specific servers on Google Play&#39;s content distribution network -- if your closest server has corruption, you&#39;ll always see this issue unless you move to a different network and a different server is selected.  I see the problem here in Colorado, and a brief Twitter survey shows a high concentration of complaints from the U.S. Midwest and Great Lakes region.  Suggestions to use a VPN have some merit -- when I VPN into Dallas, I can successfully update/install these problematic packages, because a non-corrupted server is chosen in that case.  (Obviously this isn&#39;t a great solution.)&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;UPDATE 2013-08-13: I heard from a Google Play engineer today.  It sounds like they&#39;re in the process of rolling out a fix, so our package updates and installs should be back to normal very soon!&lt;/em&gt;
&lt;/p&gt;

&lt;center&gt;
&lt;img src=&#34;https://cafbit.com/resource/androidinvalid/PackageFileIsInvalid.png&#34; /&gt;
&lt;/center&gt;

&lt;p&gt;
I&#39;ve observed this problem on the following devices:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Galaxy Nexus (Android 4.2)&lt;/li&gt;
&lt;li&gt;Nexus 10 (Android 4.3)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
To investigate the problem, I tried downloading the recently released Twitter 4.1.4 package, and compared the downloaded package file (temporarily stored in
&lt;tt&gt;/data/data/com.android.providers.downloads/cache/downloadfile.apk&lt;/tt&gt;) to a known good version.
&lt;/p&gt;

&lt;p&gt;
A hex dump of an uncorrupted Twitter 4.1.4 package looks like this around offset 0x0200000:
&lt;pre&gt;
01fffc0: 6e69 2067 6fcc 8872 6d65 6b2e 0028 2b42  ni go..rmek..(+B
01fffd0: 6972 2069 6e73 616e 206d c4b1 73c4 b16e  ir insan m..s..n
01fffe0: 2079 6f6b 7361 2062 6972 2062 696c 6769   yoksa bir bilgi
01ffff0: 7361 7961 7220 6dc4 b13f 000c 0c42 6f79  sayar m..?...Boy
0200000: 7574 3a20 252e 3166 6b00 0f11 4b6f 6e75  ut: %.1fk...Konu
0200010: 6d75 2064 65c4 9f69 c59f 7469 7200 0303  mu de..i..tir...
0200020: 5369 6c00 2122 2225 3124 7322 2022 2532  Sil.!&#34;&#34;%1$s&#34; &#34;%2
0200030: 2473 2220 6c69 7374 6573 696e 6920 6f6c  $s&#34; listesini ol
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
A hex dump of the corrupted Twitter apk looks like this around offset 0x0200000:
&lt;pre&gt;
01fffc0: 6e69 2067 6fcc 8872 6d65 6b2e 0028 2b42  ni go..rmek..(+B
01fffd0: 6972 2069 6e73 616e 206d c4b1 73c4 b16e  ir insan m..s..n
01fffe0: 2079 6f6b 7361 2062 6972 2062 696c 6769   yoksa bir bilgi
&lt;span style=&#34;color: #FF0000&#34;&gt;01ffff0: 504b 0304 1400 0800 0800 e27c 0543 2d70  PK.........|.C-p
0200000: 8d5b c420 0100 986f 0200 1d00 0400 6173  .[. ...o......as
0200010: 7365 7473 2f66 6f6e 7473 2f52 6f62 6f74  sets/fonts/Robot
0200020: 6f2d 4c69 6768 742e 7474 66fe ca00 00ec  o-Light.ttf.....
0200030: 9d07 7c54 55fa f74f 994c 0a21 bd00 8190  ..|TU..O.L.!....&lt;/span&gt;
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
At 16 bytes before the 2-megabyte mark, the corrupted file begins repeating the contents of the beginning of the file, including the ZIP header.  It looks like a common programming error when dealing with buffered I/O streams.  I first suspected that the Play Store app or the Android framework on my devices had such an error, but then I used &lt;tt&gt;tcpdump&lt;/tt&gt; to examine the actual HTTP traffic as seen from my router:
&lt;/p&gt;

&lt;p&gt;
&lt;pre&gt;
&lt;em&gt;GET http://r15---sn-qxo7sn7s.c.android.clients.google.com/market/GetBinary/com.twitter.android/420?...&lt;/em&gt;
22:01:25.861259 IP 74.125.x.x.80 &gt; 192.168.x.x.39431: Flags [.], seq 2097056:2098516, ack 527, win 245, length 1460
...
0x0230:  2073 cca7 6966 7265 6e69 2067 6fcc 8872  .s..ifreni.go..r
0x0240:  6d65 6b2e 0028 2b42 6972 2069 6e73 616e  mek..(+Bir.insan
0x0250:  206d c4b1 73c4 b16e 2079 6f6b 7361 2062  .m..s..n.yoksa.b
0x0260:  6972 2062 696c 6769 &lt;span style=&#34;color: #FF0000&#34;&gt;504b 0304 1400 0800&lt;/span&gt;  ir.bilgi&lt;span style=&#34;color: #FF0000&#34;&gt;PK......
0x0270:  0800 e27c 0543 2d70 8d5b c420 0100 986f  ...|.C-p.[.....o
0x0280:  0200 1d00 0400 6173 7365 7473 2f66 6f6e  ......assets/fon
0x0290:  7473 2f52 6f62 6f74 6f2d 4c69 6768 742e  ts/Roboto-Light.
0x02a0:  7474 66fe ca00 00ec 9d07 7c54 55fa f74f  ttf.......|TU..O&lt;/span&gt;
&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
Sure enough, the corruption was present in the stream &lt;em&gt;as sent from Google&#39;s web server&lt;/em&gt;.  I assume that the bug is in Google&#39;s web server code, or in some intermediate package processing step at the Play Store.  Either way, we&#39;ll just have to wait for Google to fix the glitch.
&lt;/p&gt;</description>
        </item>
    
        <item>
          <title>Google Fiber Tourism: Plugging into the glass at the Kansas City Hacker House</title>
          <link>https://cafbit.com/post/google_fiber_tourism/</link>
          <pubDate>Sat, 29 Dec 2012 06:24:39 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/google_fiber_tourism/</guid>
          <description>&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/googlefibertourism/hackerdesk-large.jpg&#34;&gt;&lt;img src=&#34;https://cafbit.com/resource/googlefibertourism/hackerdesk.jpg&#34;&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;
While finishing up my holiday travel, I decided to stop in for a couple of days at the Kansas City &lt;a href=&#34;https://www.airbnb.com/rooms/841162&#34;&gt;Hacker House&lt;/a&gt;, a place for aspiring technology entrepreneurs to live and work on their projects while connected to the &lt;a href=&#34;http://fiber.google.com/about/&#34;&gt;Google Fiber&lt;/a&gt; gigabit network.  Unlike my &lt;a href=&#34;http://cafbit.com/entry/google_fiber&#34;&gt;previous Google Fiber experience&lt;/a&gt;, I had an opportunity to plug my laptop directly into the network via gigabit ethernet and run some more tests.
&lt;/p&gt;

&lt;h2&gt;Legacy Tests&lt;/h2&gt;

&lt;p&gt;I first ran a few tests of legacy network usage -- uploading and downloading large files from various services.&lt;/p&gt;

&lt;table class=&#34;tabdata&#34;&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;test&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;file size&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;time&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;effective bitrate&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Google Drive - upload&lt;/td&gt;&lt;td&gt;256MB&lt;/td&gt;&lt;td&gt;400 seconds&lt;/td&gt;&lt;td&gt;5.3687 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Google Drive - download&lt;/td&gt;&lt;td&gt;256MB&lt;/td&gt;&lt;td&gt;289 seconds&lt;/td&gt;&lt;td&gt;7.4307 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Dropbox - upload&lt;/td&gt;&lt;td&gt;256MB&lt;/td&gt;&lt;td&gt;31.7 seconds&lt;/td&gt;&lt;td&gt;67.655 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Dropbox - download&lt;/td&gt;&lt;td&gt;256MB&lt;/td&gt;&lt;td&gt;67.6 seconds&lt;/td&gt;&lt;td&gt;31.779 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Ubuntu 12.10 (mirror.anl.gov)&lt;/td&gt;&lt;td&gt;753.293MB&lt;/td&gt;&lt;td&gt;61.4 seconds&lt;/td&gt;&lt;td&gt;102.86 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Ubuntu 12.10 (bittorrent)&lt;/td&gt;&lt;td&gt;753.293MB&lt;/td&gt;&lt;td&gt;342 seconds&lt;/td&gt;&lt;td&gt;18.477 Mbps (peak 31.932)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Linux Mint 12 (bittorrent; 72/325 seeds)&lt;/td&gt;&lt;td&gt;1027.468MB&lt;/td&gt;&lt;td&gt;283 seconds&lt;/td&gt;&lt;td&gt;30.456 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;
It looks like Google Drive wasn&#39;t having a good day.  Dropbox, on the other hand, really screamed.  (Although not as much as you might expect on a gigabit connection.)  It was nice to be able to download Ubuntu in 61 seconds from a well-connected server.  Bittorrent didn&#39;t perform well, though -- I suspect you&#39;d need to be downloading a much larger file from many more seeds before you&#39;d see Bittorrent have time to ramp up the connections and compare favorably.
&lt;/p&gt;

&lt;p&gt;
All tests were performed to and from a local ramdisk, to avoid any hard drive I/O bottlenecks.  However, the remote servers are likely using spinning disks that are contending with many other users.
&lt;/p&gt;

&lt;h2&gt;Speedtest.net tests&lt;/h2&gt;

&lt;p&gt;
The &lt;a href=&#34;http://www.speedtest.net/&#34;&gt;Speedtest.net&lt;/a&gt; tests really aren&#39;t very useful for Google Fiber, since the servers aren&#39;t really set up for measuring high-bandwidth connections.  You really end up measuring the server&#39;s capabilities and the throughput of various intermediate networks.  Nevertheless, here are a couple of tests:
&lt;/p&gt;

&lt;img src=&#34;https://cafbit.com/resource/googlefibertourism/speedtest-lawrence.png&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/googlefibertourism/speedtest-paloalto.png&#34;&gt;

&lt;p&gt;
I tested with several other Speedtest.net servers, and all the results varied too much to be useful.
&lt;/p&gt;

&lt;h2&gt;Google Fiber Speed Test&lt;/h2&gt;

&lt;p&gt;
To provide users with a reliable way of measuring the bandwidth to their home, Google provides a
Google Fiber Speed Test for testing the connection from the home to a server on the Google Fiber network.  (Google Fiber customers can &lt;a href=&#34;http://speedtest.googlefiber.net/&#34;&gt;access the server&lt;/a&gt;, but it doesn&#39;t appear to be accessible from the outside.)
&lt;/p&gt;

&lt;p&gt;
&lt;img src=&#34;https://cafbit.com/resource/googlefibertourism/googlefiberspeedtest.png&#34;&gt;
&lt;/p&gt;

&lt;p&gt;
The primary differences between Google&#39;s speed tests and the other speed tests seem to be:
&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Google&#39;s server is located on the Google Fiber network in Kansas City, a mere 4 hops and 1.337ms of latency away from Google Fiber customers.  This means that the Google Fiber Speed Test can more accurately measure the capability of a customer&#39;s last-mile link.  (This also means it&#39;s perhaps less useful as a test for measuring access to resources outside of Kansas City.)&lt;/li&gt;
&lt;li&gt;The server is presumably provisioned well enough to handle tests from gigabit customers.&lt;/li&gt;
&lt;li&gt;Google&#39;s test opens a large number of simultaneous connections -- as many as 64 from my &lt;tt&gt;tcpdump&lt;/tt&gt; observations.  This may help with issues related to TCP window size, and possibly mitigate the negative effects of TCP congestion control should one of the connections miss a packet.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;Network topology&lt;/h2&gt;

&lt;p&gt;
Google Fiber has considerably increased their peering arrangements since my last visit.  They seem to have good peering with the following networks that I noticed:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Level 3 - Chicago&lt;/li&gt;
&lt;li&gt;XO - Chicago&lt;/li&gt;
&lt;li&gt;Facebook (Rackspace ORD1) - Chicago&lt;/li&gt;
&lt;li&gt;Inteliquent - Chicago&lt;/li&gt;
&lt;li&gt;Kansas Research and Education Network (KanREN) - Kansas City&lt;/li&gt;
&lt;li&gt;Level 3 - Dallas&lt;/li&gt;
&lt;li&gt;Level 3 - Denver&lt;/li&gt;
&lt;li&gt;Comcast (Equinix Great Oaks) - San Jose&lt;/li&gt;
&lt;li&gt;Level 3 - San Jose&lt;/li&gt;
&lt;li&gt;Amazon - San Francisco&lt;/li&gt;
&lt;li&gt;Google - various&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
(Who knew that Facebook even had their own nationwide network?  If you see &lt;tt&gt;tfbnw.net&lt;/tt&gt; addresses in your traceroutes, the &lt;tt&gt;tfbnw&lt;/tt&gt; stands for &#34;the facebook network&#34;.)
&lt;/p&gt;
&lt;p&gt;
IPv6 seems to be functioning properly, according to various online testers.  (I did have some issues reaching my 6to4-connected home network via IPv6, for some reason.)
&lt;/p&gt;

&lt;h2&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;
The file transfer tests -- old-fashioned &#34;move this big file from one hard drive on the network to some other hard drive&#34; -- are probably not the best tests of a next-generation gigabit service such as Google Fiber.  Nor are most other &#34;download&#34; applications.  (What&#39;s the point of being able to download four seasons of &lt;em&gt;Breaking Bad&lt;/em&gt; in 3 minutes, when it takes 30 hours to watch?)  Ultimately, unlocking the true potential of home gigabit connections will rely on the development of new and interesting applications.  I predict a lot of live media, immersive telepresence, and rich collaboration applications will arise from this experiment.
&lt;/p&gt;

&lt;p&gt;
Thanks to Ben Barreth and the residents of the &lt;a href=&#34;https://www.airbnb.com/rooms/841162&#34;&gt;Hacker House&lt;/a&gt; for having me over!
&lt;/p&gt;</description>
        </item>
    
        <item>
          <title>Hanging out on the job: Using Google Hangouts for collaborative telepresence</title>
          <link>https://cafbit.com/post/hanging_out_on_the_job/</link>
          <pubDate>Wed, 21 Nov 2012 04:51:08 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/hanging_out_on_the_job/</guid>
          <description>&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/hangouts/dayone-large.jpg&#34;&gt;&lt;img src=&#34;https://cafbit.com/resource/hangouts/dayone.jpg&#34; /&gt;&lt;/a&gt;
My work and telepresence setup.
&lt;/div&gt;
&lt;p&gt;
As a work-from-home software engineer, I&#39;m always looking for ways to improve communication with co-workers and clients to help bridge the distance gap.  At the beginning of October, a colleague and I decided to devote the month to an extreme collaboration experiment we called &lt;a href=&#34;http://www.paulgraham.com/makersschedule.html&#34;&gt;Maker&#39;s Month&lt;/a&gt;.  We had been using &lt;a href=&#34;http://www.google.com/+/learnmore/hangouts/&#34;&gt;Google Hangouts&lt;/a&gt; for meetings with great effectiveness, so we asked ourselves: &lt;em&gt;Why not leave a hangout running all day, to provide the illusion of working in the same room?&lt;/em&gt;  To that end, we decided to take our two offices -- separated spatially by 1,000 miles -- and merge them into one with the miracle of modern telecommunications.
&lt;/p&gt;
&lt;p&gt;
We began by establishing some work parameters: We would have a meeting every morning to discuss the goals of the day, then mute our microphones for most of the next 6 to 7 &#34;core office hours&#34; while the hangout was left running.  During the day we could see each other working, ask questions, engage in impromptu integration sessions, and generally pretend like we were working under the same roof.  At the end of the day, we would have another meeting to discuss our accomplishments, adjust the project schedule, and set goals for the following day.  We would then adjourn the hangout and work independently in &#34;offline&#34; mode.
&lt;/p&gt;
&lt;p&gt;
There were a handful of questions we were hoping to answer during the course of this experiment:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How much bandwidth would this telepresence cost, in terms of both instantaneous bitrate and total data usage?&lt;/li&gt;
&lt;li&gt;What audio/video gear would give us the best experience, and help avoid the usual trouble areas?  (Ad-hoc conferencing setups are notorious for annoying glitches such as remote echo.)&lt;/li&gt;
&lt;li&gt;Would Google even allow us to keep such long-duration hangouts running, or to use such a large number of hangout-hours in a month?  (Unlike peer-to-peer protocols such as RTP/WebRTC/etc., hangout media streams are actually switched in the cloud and consume the CPU/bandwidth resources of Google.)&lt;/li&gt;
&lt;li&gt;Do extended telepresence sessions provide real value to software development teams?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
While Google Hangouts supports up to nine people in a hangout, our experiment only involved two people. (Our initial plans to bring a third team member into the hangout never materialized.)
&lt;/p&gt;

&lt;div style=&#34;clear: both;&#34;&gt;&lt;/div&gt;

&lt;h2&gt;Technical details&lt;/h2&gt;

&lt;p&gt;
This wouldn&#39;t be a proper &lt;em&gt;Caffeinated Bitstream&lt;/em&gt; post without some graphs and figures, so here are some charts showing the overall bandwidth usage:
&lt;/p&gt;
&lt;img src=&#34;https://cafbit.com/resource/hangouts/session-usage.png&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/hangouts/month-usage.png&#34;&gt;
&lt;p&gt;
The first chart shows the bandwidth usage of a typical two-person hangout session, which uses about 750-1000 kbps in each direction (when the connection settings are configured for &#34;fast connection&#34;).  The aberrations in the chart are due to changing hangout parameters (i.e. screen sharing instead of video, or the remote party dropping off.)  The second chart shows the bandwidth usage for my house during the month of October.  The hangout sessions are likely the bulk of this usage, but it also includes occasional movie streaming, Ubuntu downloads, software updates, and such.  I sometimes hear people comment that the bandwidth caps imposed by some internet service providers can&#39;t be exceeded by legitimate use of the network, but I can easily imagine many telepresence scenarios that would quite legitimately push users over the limit.  Fortunately, our usage is fairly modest, and my provider doesn&#39;t impose caps, anyway.
&lt;/p&gt;

&lt;p&gt;
My hangout hardware consists of:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A desktop computer with a quad-core Core i7 920 2.67Ghz processor and 8GB of RAM, running Ubuntu Linux&lt;/li&gt;
&lt;li&gt;A dedicated LCD monitor&lt;/li&gt;
&lt;li&gt;A &lt;a href=&#34;http://www.logitech.com/en-us/support/webcams/hd-pro-webcam-c910&#34;&gt;Logitech HD Pro Webcam C910&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A &lt;a href=&#34;http://bluemic.com/yeti/&#34;&gt;Blue Yeti microphone&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A stereo system with good speakers, for audio output.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
I&#39;ve occasionally run Google Hangouts on my mid-2010 MacBook Pro, but the high CPU usage eventually revs up the fan to an annoying degree.  The desktop computer doesn&#39;t seem to noticeably increase its fan noise, although I do have it tucked away in a corner.  I&#39;ve found that having a dedicated screen for the hangout really helps the telepresence illusion.  The Yeti microphone is awesome, but the C910&#39;s built-in microphone is also surprisingly great.  In fact, my colleague can&#39;t tell much of a difference between the two.  I&#39;ve noticed that the use of some other (perhaps sub-standard) microphones seems to thwart the echo cancellation built-in to Google Hangouts, resulting in echo that makes it almost impossible to carry on a conversation.  
&lt;/p&gt;

&lt;p&gt;
In addition to its thirst for bandwidth, Google Hangouts also demands a hefty chunk of processor time (and thus, power usage) on my equipment:
&lt;/p&gt;
&lt;table class=&#34;tabdata&#34;&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;system&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;cpu usage&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;quiescent power&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;hangout power&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;hangout power increase&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;4-core Core i7 920 2.67Ghz desktop&lt;/td&gt;&lt;td&gt;62%&lt;/td&gt;&lt;td&gt;75W&lt;/td&gt;&lt;td&gt;80W&lt;/td&gt;&lt;td&gt;5W&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;2-core Core i7 2.66Ghz mid-2010 MacBook Pro&lt;/td&gt;&lt;td&gt;77%&lt;/td&gt;&lt;td&gt;13W&lt;/td&gt;&lt;td&gt;38W&lt;/td&gt;&lt;td&gt;25W&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class=&#34;fineprint&#34;&gt;&lt;p style=&#34;margin-top: 2px&#34;&gt;
(Note: CPU usage is measured such that full usage of a single core is 100%.  The usage is the sum of various processes related to delivering the hangout experience.
On Linux: &lt;tt&gt;GoogleTalkPlugin, pulseaudio, chrome, compiz, Xorg.&lt;/tt&gt;
On Mac:  &lt;tt&gt;GoogleTalkPlugin, Google Chrome Helper, Google Chrome, WindowServer, VDCAssistant&lt;/tt&gt;.
Power was measured with an inline &lt;a href=&#34;http://www.p3international.com/products/special/p4400/p4400-ce.html&#34;&gt;Kill A Watt&lt;/a&gt; meter.)
&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;
I figure that using my desktop machine for daily hangouts has a marginal electrical cost of around $0.06/month.  (Although keeping this desktop running without suspending it is probably costing me around $4.74/month.)  Changing the hangout settings to &#34;slow connection&#34; roughly reduces the CPU usage by half.
&lt;/p&gt;

&lt;p&gt;
Why does Google Hangouts use so much CPU and bandwidth?  I think it all comes down to the use of H.264 &lt;a href=&#34;http://en.wikipedia.org/wiki/Scalable_Video_Coding&#34;&gt;Scalable Video Coding&lt;/a&gt; (SVC), a bitrate peeling scheme where the video encoder actually produces multiple compressed video streams at different bitrates.  The higher-bitrate streams are encoded relative to information in the lower-bitrate streams, so the total required bitrate is fortunately much less than the sum of otherwise independent streams, but it is higher than a single stream.  The &#34;video switch in the cloud&#34; operated by Google (or perhaps &lt;a href=&#34;http://www.vidyo.com/&#34;&gt;Vidyo&lt;/a&gt;, the provider of the underlying video technology) can determine the bandwidth capacity of the other parties and peel away the high-bitrate layers if necessary.  Unfortunately, not only does SVC somewhat increase the bandwidth requirements, but it also means that the Google Talk Plugin cannot leverage any standard H.264 hardware encoders that may be present on the user&#39;s computer.  Thus, a software encoder is used and the CPU usage is high.  The design decision to use SVC probably pays off when three people or more are using a hangout.
&lt;/p&gt;

&lt;p&gt;
One downside to using Google Hangouts for extended telepresence sessions is the periodic &#34;Are you still there?&#34; prompt, which seems to appear roughly every 2.5 hours.  If you don&#39;t answer in the affirmative, you will be dropped from the hangout after a few minutes.  Sometimes when I&#39;ve stepped out of the office for coffee, I&#39;ll miss the prompt and get disconnected.  I understand why Google does this, though, and reconnecting to the same hangout is pretty easy.  Even with our excessive use of Google Hangouts, we haven&#39;t encountered any other limits to the service.
&lt;/p&gt;

&lt;div style=&#34;clear: both;&#34;&gt;&lt;/div&gt;

&lt;h2&gt;Telepresence effectiveness&lt;/h2&gt;

&lt;p&gt;
Video conferencing has always offered some obvious communication advantages, and Google Hangouts is no exception.  The experience is much better than talking on the phone, as body language can really help convey meaning.  In many ways, it does help close the distance gap and simulate being in the same room: team members can show artifacts (such as devices and mobile phone apps) and see at a glance if other team members are present, absent, working hard on a problem, or perhaps available for interruption.  We made heavy use of the screen sharing feature, and even took advantage of the shared YouTube viewing on several occasions.  We didn&#39;t engage in &lt;a href=&#34;http://en.wikipedia.org/wiki/Pair_programming&#34;&gt;pair programming&lt;/a&gt; in this experiment, although remote pair programming is &lt;a href=&#34;http://news.ycombinator.com/item?id=1588761&#34;&gt;not unheard of&lt;/a&gt;.  The biggest benefit of telepresence for geographically distributed teams seems to be keeping team members focused and engaged, as being able to see other team members working can be a source of motivation.
&lt;/p&gt;

&lt;p&gt;
For me, the biggest downside to frequent use of Google Hangouts is the &#34;stream litter&#34; problem: Every hangout event appears in your Google+ stream forever, unless you manually delete it.  While it&#39;s only visible to the hangout participants, it&#39;s really annoying to have to sift through a hundred hangout events while I&#39;m looking for an unrelated post in my Google+ stream.  Also, it&#39;s sometimes awkward when I want to share the screen from my work computer while using a different computer for the hangout.  I end up joining the hangout a second time from my work computer, only to have nasty audio feedback ensue until I mute the microphone and speaker.
&lt;/p&gt;

&lt;h2&gt;Conclusions&lt;/h2&gt;

&lt;p&gt;
I think that using Google Hangouts for extended work sessions adds a lot of value, and I&#39;ll continue to use it.  It would be interesting to try other video conferencing solutions to see how they compare.
&lt;/p&gt;
&lt;p&gt;
For the impatient people who just scrolled down to &#34;Conclusions&#34; right away, here&#39;s the &lt;tt&gt;tl;dr&lt;/tt&gt;:
&lt;/p&gt;
Pros:
&lt;ul&gt;
&lt;li&gt;Continuous visual of other team members increases the opportunities for impromptu discussions and helps motivation.&lt;/li&gt;
&lt;li&gt;The &#34;same room&#34; illusion helps close the distance gap associated with telework.
&lt;li&gt;Good quality audio and video.&lt;/li&gt;
&lt;li&gt;Easily accessible from GMail or Google+.&lt;/li&gt;
&lt;li&gt;Screen sharing.&lt;/li&gt;
&lt;li&gt;Shared YouTube viewing.&lt;/li&gt;
&lt;/ul&gt;
Cons:
&lt;ul&gt;
&lt;li&gt;Relatively high (but manageable) bandwidth and CPU requirements.&lt;/li&gt;
&lt;li&gt;Google+ stream littered with hangout events.&lt;/li&gt;
&lt;li&gt;2.5-hour &#34;Are you still there?&#34; prompt.&lt;/li&gt;
&lt;li&gt;When eating doughnuts in front of team members, can&#39;t offer some for everyone.&lt;/li&gt;
&lt;/ul&gt;</description>
        </item>
    
        <item>
          <title>A quick survey of C&#43;&#43;11 feature support</title>
          <link>https://cafbit.com/post/cplusplus_11_features/</link>
          <pubDate>Sun, 07 Oct 2012 01:54:21 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/cplusplus_11_features/</guid>
          <description>&lt;p&gt;
I recently conducted a quick-and-dirty survey of C++11 (formerly known as C++0x) features available on various platforms and compilers that I had lying around.  My testing was not authoritative nor rigorous.  (For example, g++ without -std=c++0x actually compiles lambdas without throwing an error, so I marked it as supported even though it does give a stern warning.)  I&#39;m posting the results here, mostly for my own future reference.
&lt;/p&gt;

&lt;div class=&#34;wide&#34;&gt;
&lt;style&gt;
table.cppdata {
    border-width: thin;
    border-style: outset;
    border-spacing: 0px;
}
table.cppdata td {
    border-width: thin;
    border-style: outset;
    padding: 2px;
    font-size: 90%;
    color: #222;
}
table.cppdata thead td {
    text-align: center;
}
table.cppdata tbody td {
    text-align: center;
}
&lt;/style&gt;
&lt;table class=&#34;cppdata&#34;&gt;
&lt;col /&gt;
&lt;col span=3 style=&#34;background-color: #e0ffe0;&#34; /&gt;
&lt;col span=4 style=&#34;background-color: #e0e0ff;&#34; /&gt;
&lt;col span=1 style=&#34;background-color: #ffe0e0;&#34; /&gt;
&lt;thead&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td colspan=3&gt;&lt;b&gt;Mac OS 10.6 / Xcode 4.2&lt;br&gt;gcc version 4.2.1&lt;br&gt;Apple clang version 3.0&lt;/b&gt;&lt;/td&gt;
    &lt;td colspan=4&gt;&lt;b&gt;Ubuntu 12.04&lt;br&gt;gcc version 4.6.3&lt;br&gt;Ubuntu clang version 3.0-6ubuntu3&lt;/b&gt;&lt;/td&gt;
    &lt;td colspan=1&gt;&lt;b&gt;Windows 7&lt;br&gt;MSVC++ 2010&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;g++&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;clang++&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;clang++ -std=c++0x&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;g++&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;g++ -std=c++0x&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;clang++&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;clang++ -std=c++0x&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;cl.exe /clr&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;__cplusplus&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;1L&lt;/td&gt;
    &lt;td&gt;1L&lt;/td&gt;
    &lt;td&gt;201103L&lt;/td&gt;
    &lt;td&gt;1L&lt;/td&gt;
    &lt;td&gt;1L&lt;/td&gt;
    &lt;td&gt;1L&lt;/td&gt;
    &lt;td&gt;201103L&lt;/td&gt;
    &lt;td&gt;199711L&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;__GXX_EXPERIMENTAL_CXX0X__&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;undef&lt;/td&gt;
    &lt;td&gt;undef&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;undef&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;undef&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;undef&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;omit space in nested template &#34;&amp;gt;&amp;gt;&#34;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;std::tr1::shared_ptr&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;std::shared_ptr&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;nullptr&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;auto&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;uniform initialization&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;for&lt;/tt&gt; range (foreach)&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;move semantics (&lt;tt&gt;std::move&lt;/tt&gt;)&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;raw string literals&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;encoded string literals&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;noexcept&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;constexpr&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;variadic templates&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;lambdas&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;decltype&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;new function declaration style&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;scoped enums&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;std::function&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;std::tr1::function&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;can autodetect need for &lt;tt&gt;std::tr1&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;
Other, probably more thorough information about C++11 feature support:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://wiki.apache.org/stdcxx/C++0xCompilerSupport&#34;&gt;C++0xCompilerSupport (Apache&#39;s C++ Standard Library Wiki)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://www.aristeia.com/C++11/C++11FeatureAvailability.htm&#34;&gt;Summary of C++11 Feature Availability in gcc and MSVC (Scott Meyers)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://blogs.msdn.com/b/vcblog/archive/2010/04/06/c-0x-core-language-features-in-vc10-the-table.aspx&#34;&gt;C++0x Core Language Features In VC10: The Table (Microsoft)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
My quick-and-dirty &lt;a href=&#34;https://cafbit.com/resource/c%2B%2B11testsuite.tar.gz&#34;&gt;test suite is available for download&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;UPDATE 2013-05-27: More recent platforms and compilers, below...&lt;/em&gt;&lt;/p&gt;

&lt;div class=&#34;wide&#34;&gt;
&lt;table class=&#34;cppdata&#34;&gt;
&lt;col /&gt;
&lt;col span=2 style=&#34;background-color: #e0ffe0;&#34; /&gt;
&lt;col span=4 style=&#34;background-color: #e0e0ff;&#34; /&gt;
&lt;thead&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td colspan=2&gt;&lt;b&gt;Mac OS 10.8 / Xcode 4.6.2&lt;br&gt;gcc version 4.2.1&lt;br&gt;Apple clang version 3.3&lt;/b&gt;&lt;/td&gt;
    &lt;td colspan=4&gt;&lt;b&gt;Ubuntu 13.04&lt;br&gt;gcc version 4.7.3&lt;br&gt;Ubuntu clang version 3.2-1~exp9ubuntu1&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;clang++&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;clang++ -std=c++11&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;g++&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;g++ -std=c++11&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;clang++&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;b&gt;clang++ -std=c++11&lt;/b&gt;&lt;/td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;__cplusplus&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;199711L&lt;/td&gt;
    &lt;td&gt;201103L&lt;/td&gt;
    &lt;td&gt;199711L&lt;/td&gt;
    &lt;td&gt;201103L&lt;/td&gt;
    &lt;td&gt;199711L&lt;/td&gt;
    &lt;td&gt;201103L&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;__GXX_EXPERIMENTAL_CXX0X__&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;undef&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;undef&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
    &lt;td&gt;undef&lt;/td&gt;
    &lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;omit space in nested template &#34;&amp;gt;&amp;gt;&#34;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;std::tr1::shared_ptr&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;std::shared_ptr&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;nullptr&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;auto&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;uniform initialization&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;for&lt;/tt&gt; range (foreach)&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;move semantics (&lt;tt&gt;std::move&lt;/tt&gt;)&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;raw string literals&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;encoded string literals&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;noexcept&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;constexpr&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;variadic templates&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;lambdas&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;decltype&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;new function declaration style&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;scoped enums&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;std::function&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;&lt;tt&gt;std::tr1::function&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
    &lt;td&gt;can autodetect need for &lt;tt&gt;std::tr1&lt;/tt&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
    &lt;td&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
</description>
        </item>
    
        <item>
          <title>Nest Learning Thermostat: Installation, battery issues, and the importance of the &#34;C&#34; wire</title>
          <link>https://cafbit.com/post/nest_learning_thermostat/</link>
          <pubDate>Thu, 30 Aug 2012 17:41:54 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/nest_learning_thermostat/</guid>
          <description>&lt;center&gt;
&lt;div class=&#34;wide&#34;&gt;
&lt;iframe class=&#34;youtube&#34; src=&#34;https://www.youtube.com/embed/WMU78ds0yiU?rel=0&#34; frameborder=&#34;0&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/center&gt;

&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/nest/furnace-large.jpg&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/nest/furnace.jpg&#34; /&gt;&lt;/a&gt;
&lt;p&gt;
My furnace&#39;s control board.  The &#34;C&#34; terminal has no connection to the thermostat in this picture.  (The white wire on the C terminal goes to the A/C.)  I connected the unused blue wire (bottom center) to the C terminal.
&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/nest/nestwiring-large.jpg&#34;&gt;
&lt;img src=&#34;https://cafbit.com/resource/nest/nestwiring.jpg&#34; /&gt;&lt;/a&gt;
&lt;p&gt;
The Nest now confirms the active &#34;C&#34; wire.
&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;
I recently bought and installed a &lt;a href=&#34;http://www.nest.com/&#34;&gt;Nest Learning Thermostat&lt;/a&gt; to replace my old non-networked thermostat.  I show the installation, demonstrate control from mobile devices, and provide a general review in the above video.
&lt;/p&gt;

&lt;p&gt;
It&#39;s been about a month since I installed the device, and I found one important issue yesterday.  My Nest dropped off the network for 7 hours, and upon investigation I discovered that the battery was low and it turned off the Wi-Fi radio to save power.  Many other people have reported problems with the battery, which is scary because your thermostat is one device that you absolutely want to work 24/7 -- you don&#39;t want your pipes freezing when you leave town and the Nest decides to run out of juice!
&lt;/p&gt;

&lt;p&gt;
It turns out that my thermostat wiring, like in many homes, does not provide a &#34;C&#34; wire (common 24VAC) for completing a circuit that provides constant power to the unit.  This sort of wiring worked great for old-fashioned mercury thermostats -- it provides a red 24VAC power wire, and &#34;call&#34; wires for turning on the fan, heat, and air conditioning.  When the thermostat needs to turn on one of those appliances, it simply closes the circuit between the red wire and the relevant call wire.  Smart thermostats rely on batteries to power their smartness when no circuit is closed.  When an appliance is running (i.e. one of those three circuits is closed), it can perform
&lt;!-- &lt;a href=&#34;http://customer.honeywell.com/techlit/PDF/50-0000s/50-8433.pdf&#34;&gt;&#34;power stealing&#34;&lt;/a&gt; --&gt;
&lt;a href=&#34;https://www.google.com/patents/US5903139&#34;&gt;&#34;power stealing&#34;&lt;/a&gt;
to sap power from the closed circuit for its operation and recharging the battery.  For simple programmable thermostats, power stealing is probably sufficient.  However, for a power-hungry device like the Nest that needs to operate a Wi-Fi radio, this mode of operation can be problematic for several reasons:
&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you live in a nice place like Colorado where you can open the windows and go days without using the heater or air conditioner, the control circuits are never closed and the Nest&#39;s battery doesn&#39;t have an opportunity to recharge.&lt;/li&gt;
&lt;li&gt;Power stealing is an imperfect backwards compatibility hack, and can&#39;t necessarily provide enough current to recharge the battery even when the appliances are operating.  This is because the current may be limited by resistance in your furnace&#39;s control board.&lt;/li&gt;
&lt;li&gt;When the HVAC appliances are not running and the battery needs to be charged, the Nest performs an even worse hack than power stealing: it pulses the heater call circuit on and off very quickly to steal some power, and hopes that the pulses are short enough to keep the furnace from activating.  I haven&#39;t noticed any problem with this, but &lt;a href=&#34;http://www.marco.org/2011/12/17/nest-incompatibility-without-c-wire&#34;&gt;at least one person has found that this wrecks havoc on their heater&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The Nest uses a &#34;Power Saving Mode&#34; of Wi-Fi to &lt;a href=&#34;http://support.nest.com/customer/portal/articles/593751-some-wi-fi-routers-can-cause-nest-to-restart-frequently-or-unexpectedly&#34;&gt;reduce the power consumption of the radio and prolong the battery life&lt;/a&gt;.  (And hopefully require less overall power than it can steal from the call circuits.)  Nest indicates that some non-conformant wireless access points may not fully support this mode, thus causing the Nest to consume more power.  (Perhaps more quickly than it can be replenished.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;
I was lucky that my thermostat wiring contained an extra, unused (blue) wire, and my furnace&#39;s control board provided a 24VAC common terminal for a &#34;C&#34; wire.  After hooking up the blue wire at the furnace and the Nest&#39;s base, I now seem to have successfully provided a 24VAC &#34;C&#34; wire to the Nest, and hopefully my battery issues are behind me.
&lt;/p&gt;

&lt;p&gt;
I do think that Nest is perhaps overly optimistic about their power stealing and circuit pulsing being able to provide adequate power to the device.  There&#39;s certainly no warning about this potential issue when you provide your wiring information to their online compatibility tool.
&lt;/p&gt;

&lt;h3&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;http://www.marco.org/2011/12/17/nest-incompatibility-without-c-wire&#34;&gt;Undocumented Nest incompatibility with single-stage wiring&lt;/a&gt; - Marco Arment of Instapaper fame reports on his experience with this issue.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://diy.stackexchange.com/questions/10482/options-for-adding-c-wire-to-thermostat&#34;&gt;Options for adding &#34;C&#34; wire to thermostat&lt;/a&gt; - Stack Exchange&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://wiki.xtronics.com/index.php/Thermostat_signals_and_wiring&#34;&gt;Thermostat signals and wiring&lt;/a&gt; - a great resource for understanding thermostat wiring.&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;http://support.nest.com/customer/portal/articles/197951&#34;&gt;When Nest needs a common &#34;C&#34; wire&lt;/a&gt; - The Nest support page for this topic (which somewhat downplays the severity of the issue).&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
    
        <item>
          <title>A Technical Look at Google Fiber</title>
          <link>https://cafbit.com/post/google_fiber/</link>
          <pubDate>Mon, 13 Aug 2012 02:05:40 &#43;0000</pubDate>
          <guid>https://cafbit.com/post/google_fiber/</guid>
          <description>&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/googlefiber/fiberspace-large.jpg&#34;&gt;&lt;img src=&#34;https://cafbit.com/resource/googlefiber/fiberspace.jpg&#34; /&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;
While visiting Kansas City recently, I decided to investigate &lt;a
href=&#34;https://fiber.google.com/&#34;&gt;Google Fiber&lt;/a&gt;, Google&#39;s ambitious
new residential gigabit Internet service they are building in Kansas
City, Kansas, and central Kansas City, Missouri.  While they haven&#39;t 
connected residential customers to the network yet, they have
provisioned service at several local businesses.  They also opened a
showroom called &#34;Fiber Space&#34; to demonstrate the service to potential
customers.
&lt;/p&gt;

&lt;p&gt;
My first stop was the &lt;a href=&#34;http://www.mudpiebakery.com/&#34;&gt;Mud Pie
Vegan Bakery and Coffeehouse&lt;/a&gt;, a neat coffee house in a historic area
of Midtown Kansas City.  Mud Pie has the Google Fiber hookup, which
customers can use via Wi-Fi or the ethernet-attached Chromebooks which
Google has provided.  I tried to convince the barista to let me borrow
the ethernet connection from a Chromebook so I could test the fast path,
but he declined due to Google not wanting people to interfere with their
hardware in such a way.  However, I found I was able to accomplish most
of my investigation goals using a combination of my laptop on Wi-Fi and
the wired Chromebooks.  I ended up hanging out at Mud Pie for several
hours, running tests and chatting with the barista and customers.
&lt;/p&gt;

&lt;p&gt;
Four blocks south of Mud Pie, Google has set up a showroom for Google
Fiber called &#34;Fiber Space.&#34;  It&#39;s a very consumer-oriented experience
aimed at selling the service to locals.  Many Google Fiber employees are
on hand to show people what hardware they&#39;ll need, and demonstrate the
Internet and TV services in virtual living rooms.
The &#34;car roller coaster&#34; set from the
&lt;a href=&#34;http://www.youtube.com/watch?v=ffHLIZh0PHg&#34;&gt;Google Fiber
promotional video&lt;/a&gt; and free snacks were also on hand.
In addition to the wired
Chromebooks on display, people can bring their laptops to try out Google
Fiber via the Wi-Fi.  However, an employee told me that they didn&#39;t
allow hooking up to the wire, citing a concern about piracy or illegal
activities or some such.  (Which sounds like a pretty weak excuse to
me.)
&lt;/p&gt;

&lt;div style=&#34;clear: both;&#34;&gt;&lt;/div&gt;

&lt;h2&gt;Speed Tests&lt;/h2&gt;

&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/googlefiber/bigfile-large.jpg&#34;&gt;&lt;img src=&#34;https://cafbit.com/resource/googlefiber/bigfile.jpg&#34; /&gt;&lt;/a&gt;
I don&#39;t always download big files.  But when I do, I download
half a gigabyte of pseudorandom bytes generated by &lt;tt&gt;/dev/urandom&lt;/tt&gt;.
&lt;/div&gt;

&lt;p&gt;
Naturally, the first thing people want to know about Google Fiber is
&lt;em&gt;how fast is it, really?&lt;/em&gt;  Unfortunately, it&#39;s difficult to
reliably measure the practical speed of the service due to the many
other bottlenecks that exist once you remove the bottleneck of the last
mile.  Also, since &lt;a href=&#34;http://gigaom.com/2012/07/31/google-fiber-in-the-real-world-heres-whats-good-and-what-needs-work/&#34;&gt;others
have performed plenty of speed tests&lt;/a&gt;, I decided to focus more on
other characteristics of the network.  However, I did run a few
throughput tests for good measure.
&lt;/p&gt;

&lt;p&gt;
Here is the result from
&lt;a href=&#34;http://www.speedtest.net/&#34;&gt;speedtest.net&lt;/a&gt;, running on the wired
Chromebook:
&lt;/p&gt;
&lt;img src=&#34;https://cafbit.com/resource/googlefiber/speedtest.png&#34; /&gt;
&lt;p&gt;
I tried running the test against servers in other locales, but the
default Palo Alto server delivered the best result.  I don&#39;t think these
tests are great measures of throughput for such high speeds, since not
only might the test servers be bottlenecked, but they may not run the
tests long enough for the TCP window size to ramp up to the connection&#39;s
true capacity.
&lt;/p&gt;

&lt;p&gt;
A slightly better test was to download very large files full of random
data from various cloud servers:
&lt;/p&gt;

&lt;div class=&#34;wide&#34;&gt;
&lt;table class=&#34;tabdata&#34;&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;data center&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;file size&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;time&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;rate&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Forethought.net (Denver)&lt;/td&gt;&lt;td&gt;100MB&lt;/td&gt;&lt;td&gt;8 seconds&lt;/td&gt;&lt;td&gt;104.858 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Forethought.net (Denver)&lt;/td&gt;&lt;td&gt;512MB&lt;/td&gt;&lt;td&gt;42 seconds&lt;/td&gt;&lt;td&gt;102.261 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Forethought.net (Denver)&lt;/td&gt;&lt;td&gt;512MB&lt;/td&gt;&lt;td&gt;41 seconds&lt;/td&gt;&lt;td&gt;104.755 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Linode (Dallas)&lt;/td&gt;&lt;td&gt;256MB&lt;/td&gt;&lt;td&gt;72 seconds&lt;/td&gt;&lt;td&gt;29.826 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Linode (Dallas)&lt;/td&gt;&lt;td&gt;256MB&lt;/td&gt;&lt;td&gt;79 seconds&lt;/td&gt;&lt;td&gt;27.183 Mbps&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;
I don&#39;t know why the Linode download was so slow, although the &lt;a href=&#34;https://cafbit.com/resource/googlefiber/googlefiber-to-linodedallas.txt&#34;&gt;outbound route&lt;/a&gt; to that server went out to California, and even across Comcast&#39;s network (!) before heading to Dallas.  The download from a server at Forethought hit a much higher bottleneck somewhere, but it&#39;s difficult to say where.
&lt;/p&gt;

&lt;div style=&#34;clear: both;&#34;&gt;&lt;/div&gt;

&lt;h2&gt;Latency Tests&lt;/h2&gt;

&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/googlefiber/diagnosticating-large.jpg&#34;&gt;&lt;img src=&#34;https://cafbit.com/resource/googlefiber/diagnosticating.jpg&#34; /&gt;&lt;/a&gt;
Going to town with the ping and traceroutes.
&lt;/div&gt;
&lt;div class=&#34;photo&#34;&gt;
&lt;a href=&#34;https://cafbit.com/resource/googlefiber/chromebook-large.jpg&#34;&gt;&lt;img src=&#34;https://cafbit.com/resource/googlefiber/chromebook.jpg&#34; /&gt;&lt;/a&gt;
At Mud Pie, a couple of Chromebooks were hooked up to Google Fiber via ethernet.
&lt;/div&gt;


&lt;p&gt;
I performed pings and traceroutes to a number of hosts, to get an idea
of Google Fiber&#39;s positioning on the network and the available peering
points for outbound packets.  These tests were conducted from the Wi-Fi
network at Mud Pie, so a few milliseconds can be attributed to local
Wi-Fi latency (see the first item on the list).
&lt;/p&gt;

&lt;div class=&#34;wide&#34;&gt;
&lt;table class=&#34;tabdata&#34;&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;td&gt;&lt;b&gt;host&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;location&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;min&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;avg&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;max&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;stddev&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;notes&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;networkbox&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;1.766&lt;/td&gt;&lt;td&gt;2.736&lt;/td&gt;&lt;td&gt;5.007&lt;/td&gt;&lt;td&gt;0.909&lt;/td&gt;&lt;td&gt;The local gateway, for reference&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;www.apple.com&lt;/td&gt;&lt;td&gt;Dallas, TX (see notes)&lt;/td&gt;&lt;td&gt;33.024&lt;/td&gt;&lt;td&gt;35.813&lt;/td&gt;&lt;td&gt;39.896&lt;/td&gt;&lt;td&gt;2.499&lt;/td&gt;&lt;td&gt;Akamai CDN node in Dallas, TX&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;google.com&lt;/td&gt;&lt;td&gt;Dallas, TX&lt;/td&gt;&lt;td&gt;10.920&lt;/td&gt;&lt;td&gt;13.888&lt;/td&gt;&lt;td&gt;17.224&lt;/td&gt;&lt;td&gt;2.046&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;youtube.com&lt;/td&gt;&lt;td&gt;Dallas, TX&lt;/td&gt;&lt;td&gt;10.760&lt;/td&gt;&lt;td&gt;12.129&lt;/td&gt;&lt;td&gt;12.787&lt;/td&gt;&lt;td&gt;0.736&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;www.kcnap.net&lt;/td&gt;&lt;td&gt;Kansas City, MO&lt;/td&gt;&lt;td&gt;75.605&lt;/td&gt;&lt;td&gt;76.977&lt;/td&gt;&lt;td&gt;78.628&lt;/td&gt;&lt;td&gt;0.902&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;xo.com&lt;/td&gt;&lt;td&gt;Washington, DC&lt;/td&gt;&lt;td&gt;82.057&lt;/td&gt;&lt;td&gt;83.959&lt;/td&gt;&lt;td&gt;85.609&lt;/td&gt;&lt;td&gt;1.021&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;www.frgp.net&lt;/td&gt;&lt;td&gt;Denver, CO&lt;/td&gt;&lt;td&gt;19.390&lt;/td&gt;&lt;td&gt;20.931&lt;/td&gt;&lt;td&gt;23.498&lt;/td&gt;&lt;td&gt;1.576&lt;/td&gt;&lt;td&gt;Major peering point in Denver&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;www.cogentco.com&lt;/td&gt;&lt;td&gt;Washington, DC&lt;/td&gt;&lt;td&gt;35.466&lt;/td&gt;&lt;td&gt;36.681&lt;/td&gt;&lt;td&gt;39.826&lt;/td&gt;&lt;td&gt;1.439&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;sparcomedia.com&lt;/td&gt;&lt;td&gt;Beaverton, OR&lt;/td&gt;&lt;td&gt;71.452&lt;/td&gt;&lt;td&gt;73.802&lt;/td&gt;&lt;td&gt;77.652&lt;/td&gt;&lt;td&gt;1.986&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;www.forethought.net&lt;/td&gt;&lt;td&gt;Denver, CO&lt;/td&gt;&lt;td&gt;47.438&lt;/td&gt;&lt;td&gt;49.155&lt;/td&gt;&lt;td&gt;52.776&lt;/td&gt;&lt;td&gt;1.642&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;cafbit.com&lt;/td&gt;&lt;td&gt;Denver, CO&lt;/td&gt;&lt;td&gt;48.177&lt;/td&gt;&lt;td&gt;52.195&lt;/td&gt;&lt;td&gt;58.210&lt;/td&gt;&lt;td&gt;3.121&lt;/td&gt;&lt;td&gt;You are here&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;www.he.net&lt;/td&gt;&lt;td&gt;Fremont, CA&lt;/td&gt;&lt;td&gt;39.671&lt;/td&gt;&lt;td&gt;42.087&lt;/td&gt;&lt;td&gt;45.346&lt;/td&gt;&lt;td&gt;2.055&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;gw.msstate.edu&lt;/td&gt;&lt;td&gt;Starkville, MS&lt;/td&gt;&lt;td&gt;119.290&lt;/td&gt;&lt;td&gt;122.218&lt;/td&gt;&lt;td&gt;129.973&lt;/td&gt;&lt;td&gt;3.324&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;www.olemiss.edu&lt;/td&gt;&lt;td&gt;Oxford, MS&lt;/td&gt;&lt;td&gt;43.335&lt;/td&gt;&lt;td&gt;45.507&lt;/td&gt;&lt;td&gt;49.076&lt;/td&gt;&lt;td&gt;1.777&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;news.ycombinator.com&lt;/td&gt;&lt;td&gt;Houston, TX&lt;/td&gt;&lt;td&gt;53.569&lt;/td&gt;&lt;td&gt;55.135&lt;/td&gt;&lt;td&gt;59.513&lt;/td&gt;&lt;td&gt;1.806&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;www.facebook.com&lt;/td&gt;&lt;td&gt;Palo Alto, CA&lt;/td&gt;&lt;td&gt;70.686&lt;/td&gt;&lt;td&gt;75.499&lt;/td&gt;&lt;td&gt;80.526&lt;/td&gt;&lt;td&gt;3.325&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;66.249.72.47&lt;/td&gt;&lt;td&gt;Mountain View, CA&lt;/td&gt;&lt;td&gt;39.154&lt;/td&gt;&lt;td&gt;42.498&lt;/td&gt;&lt;td&gt;45.488&lt;/td&gt;&lt;td&gt;2.106&lt;/td&gt;&lt;td&gt;Last Googlebot host to visit cafbit.com&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;drive.google.com&lt;/td&gt;&lt;td&gt;Dallas, TX&lt;/td&gt;&lt;td&gt;12.865&lt;/td&gt;&lt;td&gt;14.449&lt;/td&gt;&lt;td&gt;19.539&lt;/td&gt;&lt;td&gt;2.079&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;a.root-servers.net&lt;/td&gt;&lt;td&gt;Tokyo, Japan&lt;/td&gt;&lt;td&gt;200.447&lt;/td&gt;&lt;td&gt;203.547&lt;/td&gt;&lt;td&gt;209.336&lt;/td&gt;&lt;td&gt;2.972&lt;/td&gt;&lt;td&gt;(anycast)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;b.root-servers.net&lt;/td&gt;&lt;td&gt;Marina Del Rey, CA&lt;/td&gt;&lt;td&gt;50.488&lt;/td&gt;&lt;td&gt;53.980&lt;/td&gt;&lt;td&gt;55.954&lt;/td&gt;&lt;td&gt;1.805&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;c.root-servers.net&lt;/td&gt;&lt;td&gt;?&lt;/td&gt;&lt;td&gt;23.478&lt;/td&gt;&lt;td&gt;26.935&lt;/td&gt;&lt;td&gt;34.285&lt;/td&gt;&lt;td&gt;4.029&lt;/td&gt;&lt;td&gt;(anycast)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;d.root-servers.net&lt;/td&gt;&lt;td&gt;College Park, MD&lt;/td&gt;&lt;td&gt;118.310&lt;/td&gt;&lt;td&gt;122.118&lt;/td&gt;&lt;td&gt;134.235&lt;/td&gt;&lt;td&gt;4.868&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;f.root-servers.net&lt;/td&gt;&lt;td&gt;Chicago, IL&lt;/td&gt;&lt;td&gt;92.451&lt;/td&gt;&lt;td&gt;93.634&lt;/td&gt;&lt;td&gt;96.799&lt;/td&gt;&lt;td&gt;1.263&lt;/td&gt;&lt;td&gt;(anycast)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;h.root-servers.net&lt;/td&gt;&lt;td&gt;Aberdeen, MD&lt;/td&gt;&lt;td&gt;45.979&lt;/td&gt;&lt;td&gt;47.852&lt;/td&gt;&lt;td&gt;49.923&lt;/td&gt;&lt;td&gt;1.313&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;i.root-servers.net&lt;/td&gt;&lt;td&gt;Brussels, Belgium&lt;/td&gt;&lt;td&gt;115.991&lt;/td&gt;&lt;td&gt;118.196&lt;/td&gt;&lt;td&gt;120.097&lt;/td&gt;&lt;td&gt;1.284&lt;/td&gt;&lt;td&gt;(anycast)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;j.root-servers.net&lt;/td&gt;&lt;td&gt;Slovenia&lt;/td&gt;&lt;td&gt;145.607&lt;/td&gt;&lt;td&gt;149.108&lt;/td&gt;&lt;td&gt;152.641&lt;/td&gt;&lt;td&gt;2.383&lt;/td&gt;&lt;td&gt;(anycast)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;k.root-servers.net&lt;/td&gt;&lt;td&gt;Miami, FL&lt;/td&gt;&lt;td&gt;77.650&lt;/td&gt;&lt;td&gt;80.063&lt;/td&gt;&lt;td&gt;89.322&lt;/td&gt;&lt;td&gt;3.588&lt;/td&gt;&lt;td&gt;(anycast)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;l.root-servers.net&lt;/td&gt;&lt;td&gt;San Jose, CA&lt;/td&gt;&lt;td&gt;47.904&lt;/td&gt;&lt;td&gt;48.733&lt;/td&gt;&lt;td&gt;49.733&lt;/td&gt;&lt;td&gt;0.561&lt;/td&gt;&lt;td&gt;(anycast)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;m.root-servers.net&lt;/td&gt;&lt;td&gt;Japan&lt;/td&gt;&lt;td&gt;144.549&lt;/td&gt;&lt;td&gt;145.707&lt;/td&gt;&lt;td&gt;151.106&lt;/td&gt;&lt;td&gt;2.059&lt;/td&gt;&lt;td&gt;(anycast)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;

&lt;p&gt;
The full ping/traceroute output &lt;a href=&#34;https://cafbit.com/resource/googlefiber/tests.txt&#34;&gt;is available&lt;/a&gt;.
&lt;/p&gt;

&lt;div style=&#34;clear: both;&#34;&gt;&lt;/div&gt;

&lt;h2&gt;Peering points&lt;/h2&gt;

&lt;p&gt;
As far as I can tell, outbound packets exit Google Fiber&#39;s network via
links to either San Jose, CA, or Dallas, TX.  In San Jose, Google Fiber
seems to be peering with Comcast and XO communications.  (Presumably at
&lt;a href=&#34;http://www.equinix.com/en_US/locations/americas/us/silicon-valley-data-centers/&#34;&gt;Equinix&#39;s
11 Great Oaks facility&lt;/a&gt;.)  In Dallas, Google Fiber seems to peer with
Level 3 and Google&#39;s main network (which is a separate autonomous system
from Google Fiber).  As you might expect, access to Google services
(such as Google Drive and YouTube) is quite snappy from the Google Fiber
network.
&lt;/p&gt;

&lt;img src=&#34;https://cafbit.com/resource/googlefiber/gfmap.png&#34; /&gt;

&lt;p&gt;
Locally, Google Fiber has a short route to the
&lt;a href=&#34;http://medicine.kumc.edu/&#34;&gt;University of Kansas
Medical Center&lt;/a&gt;, but I&#39;m not sure who else they peer with in Kansas City.
They definitely do not peer with &lt;a href=&#34;http://www.kcnap.net/&#34;&gt;KC
NAP&lt;/a&gt;.
&lt;/p&gt;

&lt;h2&gt;IPv6&lt;/h2&gt;

&lt;p&gt;
While on Mud Pie&#39;s network, my laptop was assigned an IPv6 address in
the fc00::/7 block which is designated for
&lt;a href=&#34;http://en.wikipedia.org/wiki/Unique_local_address&#34;&gt;unique local
addresses&lt;/a&gt;.  However, I&#39;m not sure what the point of this is.  I
definitely could not reach the IPv6 internet via ping6.
&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;
Google Fiber is fast.  If it was available in my neighborhood, I&#39;d sign
up.
&lt;/p&gt;

&lt;p&gt;&lt;em&gt;
UPDATE 2012-12-28: I&#39;ve made another visit to Kansas City... see my post about &lt;a href=&#34;https://cafbit.com/entry/google_fiber_tourism&#34;&gt;plugging into the ethernet at the Hacker House.&lt;/a&gt;
&lt;/em&gt;&lt;/p&gt;
</description>
        </item>
    

  </channel>
</rss>
