#ifndef PLS_LIBRARY_H
#define PLS_LIBRARY_H

#include <utility>

#include "pls/algorithms/invoke.h"
#include "pls/algorithms/for_each.h"
#include "pls/algorithms/reduce.h"
#include "pls/algorithms/loop_partition_strategy.h"

#include "pls/internal/scheduling/scheduler.h"
#include "pls/internal/scheduling/strain_local_resource.h"
#include "pls/internal/base/stack_allocator.h"

#include "pls/internal/helpers/range.h"
#include "pls/internal/helpers/member_function.h"

namespace pls {

// 'basic' for-join APIs
using internal::scheduling::scheduler;
using internal::base::heap_stack_allocator;
using internal::base::mmap_stack_allocator;
template<typename Function>
static void spawn(Function &&function) {
  scheduler::spawn(std::forward<Function>(function));
}
template<typename Function>
static void spawn_and_sync(Function &&function) {
  scheduler::spawn_and_sync(std::forward<Function>(function));
}
static void sync() {
  scheduler::sync();
}
template<typename Function>
static void serial(Function &&function) {
  scheduler::serial(std::forward<Function>(function));
}

// strain local resource support (rather low-level)
using internal::scheduling::strain_local_resource;

// general helpers that can be handy when using PLS
template<class C, typename R, typename ...ARGS>
using member_function = internal::helpers::member_function<C, R, ARGS...>;
using internal::helpers::range;

// parallel patterns API
using algorithm::invoke;
using algorithm::for_each;
using algorithm::for_each_range;
using algorithm::reduce;

using algorithm::dynamic_strategy;
using algorithm::fixed_strategy;
}

#endif
