[fit][tests] Use std::thread in tests instead of std::async.

It turns out that std::async wasn't actually creating threads
so we weren't actually testing concurrent behavior.  Now we are.

Test: fit-test
Change-Id: I17c4942f0b11435e69ae43aa992ed0d250dded12
diff --git a/system/utest/fit/examples/utils.cpp b/system/utest/fit/examples/utils.cpp
index 96b1e21..ae11061 100644
--- a/system/utest/fit/examples/utils.cpp
+++ b/system/utest/fit/examples/utils.cpp
@@ -9,7 +9,6 @@
 // You do not need to include these headers just to use |fit::promise|
 // or |fit::future|.
 #include <chrono>
-#include <future>
 #include <thread>
 
 namespace utils {
@@ -26,10 +25,10 @@
 }
 
 void resume_in_a_little_while(fit::suspended_task task) {
-    std::async(std::launch::async, [task]() mutable {
+    std::thread([task]() mutable {
         std::this_thread::sleep_for(std::chrono::milliseconds(50));
         task.resume_task();
-    });
+    }).detach();
 }
 
 } // namespace utils
diff --git a/system/utest/fit/sequencer_tests.cpp b/system/utest/fit/sequencer_tests.cpp
index 6b74312..13161a2 100644
--- a/system/utest/fit/sequencer_tests.cpp
+++ b/system/utest/fit/sequencer_tests.cpp
@@ -4,9 +4,10 @@
 
 #include <unistd.h>
 
-#include <future> // for std::async
 #include <string>
+#include <thread>
 
+#include <lib/fit/bridge.h>
 #include <lib/fit/sequencer.h>
 #include <lib/fit/single_threaded_executor.h>
 #include <unittest/unittest.h>
@@ -86,19 +87,30 @@
     uint64_t run_count = 0;
 
     // Schedule work from a few threads, just to show that we can.
-    for (int i = 0; i < 4; i++) {
-        std::async(std::launch::async, [&]() mutable {
-            for (int j = 0; j < 100; j++) {
-                executor.schedule_task(
-                    fit::make_promise([&] { run_count++; }).wrap_with(seq));
-                sleep(0);
-            }
-        });
+    constexpr int num_threads = 4;
+    constexpr int num_tasks_per_thread = 100;
+    std::thread threads[num_threads];
+    for (int i = 0; i < num_threads; i++) {
+        fit::bridge bridge;
+        threads[i] =
+            std::thread([&, completer = std::move(bridge.completer())]() mutable {
+                for (int j = 0; j < num_tasks_per_thread; j++) {
+                    executor.schedule_task(
+                        fit::make_promise([&] { run_count++; }).wrap_with(seq));
+                    usleep(1);
+                }
+                completer.complete_ok();
+            });
+        executor.schedule_task(bridge.consumer().promise());
     }
 
     // Run the tasks.
     executor.run();
-    EXPECT_EQ(4 * 100, run_count);
+    for (int i = 0; i < num_threads; i++)
+        threads[i].join();
+
+    // We expect all tasks to have run.
+    EXPECT_EQ(num_threads * num_tasks_per_thread, run_count);
 
     END_TEST;
 }
diff --git a/system/utest/fit/single_threaded_executor_tests.cpp b/system/utest/fit/single_threaded_executor_tests.cpp
index 61bf469..cac5618 100644
--- a/system/utest/fit/single_threaded_executor_tests.cpp
+++ b/system/utest/fit/single_threaded_executor_tests.cpp
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <future> // for std::async
+#include <thread>
 
 #include <lib/fit/defer.h>
 #include <lib/fit/single_threaded_executor.h>
@@ -48,7 +48,6 @@
     fit::single_threaded_executor executor;
     uint64_t run_count[5] = {};
     uint64_t resume_count[5] = {};
-    uint64_t resume_count4b = 0;
 
     // Schedule a task that suspends itself and immediately resumes.
     executor.schedule_task(fit::make_promise([&](fit::context& context)
@@ -79,10 +78,10 @@
                                                  -> fit::result<> {
         if (++run_count[2] == 100)
             return fit::ok();
-        std::async(std::launch::async, [&, s = context.suspend_task()]() mutable {
+        std::thread([&, s = context.suspend_task()]() mutable {
             resume_count[2]++;
             s.resume_task();
-        });
+        }).detach();
         return fit::pending();
     }));
 
@@ -101,14 +100,16 @@
                                                  -> fit::result<> {
         if (++run_count[4] == 100)
             return fit::ok();
-        std::async(std::launch::async, [&, s = context.suspend_task()]() mutable {
-            resume_count[4]++;
+
+        // Race two threads to resume the task.  Either can win.
+        // This is safe because these threads don't capture references to
+        // local variables that might go out of scope when the test exits.
+        std::thread([s = context.suspend_task()]() mutable {
             s.resume_task();
-        });
-        std::async(std::launch::async, [&, s = context.suspend_task()]() mutable {
-            resume_count4b++; // use a different variable to avoid data races
+        }).detach();
+        std::thread([s = context.suspend_task()]() mutable {
             s.resume_task();
-        });
+        }).detach();
         return fit::pending();
     }));
 
@@ -123,8 +124,6 @@
     EXPECT_EQ(1, run_count[3]);
     EXPECT_EQ(0, resume_count[3]);
     EXPECT_EQ(100, run_count[4]);
-    EXPECT_EQ(99, resume_count[4]);
-    EXPECT_EQ(99, resume_count4b);
 
     END_TEST;
 }
@@ -160,7 +159,7 @@
         [&, d = fit::defer([&] { destruction[2]++; })](fit::context& context)
             -> fit::result<> {
             run_count[2]++;
-            std::async(std::launch::async, [s = context.suspend_task()] {});
+            std::thread([s = context.suspend_task()] {}).detach();
             return fit::pending();
         }));