blob: ad38d1d88e2fcf89be6158f7cc12409766b6884c [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "promise_example1.h"
#include <string>
#include <lib/fit/promise.h>
#include <lib/fit/single_threaded_executor.h>
#include "utils.h"
// This example demonstrates sequencing of tasks using combinators.
namespace promise_example1 {
fit::promise<int, std::string> pick_bananas(int hours) {
return fit::make_promise([hours, time = 0, harvest = 0](fit::context& context) mutable
-> fit::result<int, std::string> {
if (time == 0) {
printf("Starting the day picking bananas for %d hours...\n", hours);
} else {
printf("... %d hour elapsed...\n", time);
}
if (random() % 7 == 0) {
return fit::error("A wild animal ate all the bananas we picked today!");
}
if (time < hours) {
// Simulate time passing.
// Here we call |suspend_task()| to obtain a |fit::suspended_task|
// which acts as a handle which will later be used by
// |resume_in_a_little_while()| to resume the task. In the
// meantime, we unwind the call stack by returning |fit::pending()|.
// Once the task is resumed, the promise's handler will restart
// execution from the top again, however it will have retained
// state (in |time| and |harvest|) from its prior execution.
utils::resume_in_a_little_while(context.suspend_task());
time++;
harvest += random() % 31;
return fit::pending();
}
return fit::ok(harvest);
});
}
fit::promise<void, std::string> eat_bananas(int appetite) {
return fit::make_promise([appetite](fit::context& context) mutable
-> fit::result<void, std::string> {
if (appetite > 0) {
printf("... eating a yummy banana....\n");
utils::resume_in_a_little_while(context.suspend_task());
appetite--;
if (random() % 11 == 0) {
return fit::error("I ate too many bananas. Urp.");
}
return fit::pending();
}
puts("Ahh. So satisfying.");
return fit::ok();
});
}
fit::promise<> prepare_simulation() {
int hours = random() % 8;
return pick_bananas(hours)
.and_then([](int harvest) -> fit::result<int, std::string> {
printf("We picked %d bananas today!\n", harvest);
if (harvest == 0)
return fit::error("What will we eat now?");
return fit::ok(harvest);
})
.and_then([](int harvest) {
int appetite = random() % 7;
if (appetite > harvest)
appetite = harvest;
return eat_bananas(appetite);
})
.or_else([](std::string error) {
printf("Oh no! %s\n", error.c_str());
return fit::error();
})
.and_then([] {
puts("*** Simulation finished ***");
})
.or_else([] {
puts("*** Restarting simulation ***");
return prepare_simulation();
});
}
void run() {
auto simulation = prepare_simulation();
fit::run_single_threaded(std::move(simulation));
}
} // namespace promise_example1