#include <pls/pls.h>
#include <iostream>

// Static memory allocation (see execution trees for how to configure)
static const int MAX_NUM_TASKS = 32;
static const int MAX_STACK_SIZE = 4096;
static const int NUM_THREADS = 8;

long fib(long n);

int main() {
  // Create a scheduler with the static amount of resources.
  // All memory and system resources are allocated here.
  pls::scheduler scheduler{NUM_THREADS, MAX_NUM_TASKS, MAX_STACK_SIZE};

  // Wake up the thread pool and perform work.
  scheduler.perform_work([&] {
    long result = fib(20);
    std::cout << "fib(20)=" << result << std::endl;
  });
  // At this point the thread pool sleeps.
  // This can for example be used for periodic work.

  // The scheduler is destroyed at the end of the scope
}

long fib(long n) {
  if (n <= 1) {
    return n;
  }

  // Example for the high level API.
  // Will run both functions in parallel as separate tasks.
  int a, b;
  pls::invoke(
      [&a, n] { a = fib(n - 1); },
      [&b, n] { b = fib(n - 2); }
  );
  return a + b;
}
