mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
203 lines
8.0 KiB
C++
203 lines
8.0 KiB
C++
//===--- TaskQueue.h - Task Execution Work Queue ----------------*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef SWIFT_BASIC_TASKQUEUE_H
|
|
#define SWIFT_BASIC_TASKQUEUE_H
|
|
|
|
#include "swift/Basic/LLVM.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/Config/config.h"
|
|
#include "llvm/Support/Program.h"
|
|
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <queue>
|
|
|
|
namespace swift {
|
|
namespace sys {
|
|
|
|
class Task; // forward declared to allow for platform-specific implementations
|
|
|
|
typedef llvm::sys::ProcessInfo::ProcessId ProcessId;
|
|
|
|
/// \brief Indicates how a TaskQueue should respond to the task finished event.
|
|
enum class TaskFinishedResponse {
|
|
/// Indicates that execution should continue.
|
|
ContinueExecution,
|
|
/// Indicates that execution should stop (no new tasks will begin execution,
|
|
/// but tasks which are currently executing will be allowed to finish).
|
|
StopExecution,
|
|
};
|
|
|
|
/// \brief A class encapsulating the execution of multiple tasks in parallel.
|
|
class TaskQueue {
|
|
/// Tasks which have not begun execution.
|
|
std::queue<std::unique_ptr<Task>> QueuedTasks;
|
|
|
|
/// The number of tasks to execute in parallel.
|
|
unsigned NumberOfParallelTasks;
|
|
|
|
public:
|
|
/// \brief Create a new TaskQueue instance.
|
|
///
|
|
/// \param NumberOfParallelTasks indicates the number of tasks which should
|
|
/// be run in parallel. If 0, the TaskQueue will choose the most appropriate
|
|
/// number of parallel tasks for the current system.
|
|
TaskQueue(unsigned NumberOfParallelTasks = 0);
|
|
virtual ~TaskQueue();
|
|
|
|
// TODO: remove once -Wdocumentation stops warning for \param, \returns on
|
|
// std::function (<rdar://problem/15665132>).
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
|
/// \brief A callback which will be executed when each task begins execution
|
|
///
|
|
/// \param Pid the ProcessId of the task which just began execution.
|
|
/// \param Context the context which was passed when the task was added
|
|
typedef std::function<void(ProcessId Pid, void *Context)> TaskBeganCallback;
|
|
|
|
/// \brief A callback which will be executed after each task finishes
|
|
/// execution.
|
|
///
|
|
/// \param Pid the ProcessId of the task which finished execution.
|
|
/// \param ReturnCode the return code of the task which finished execution.
|
|
/// \param Output the output from the task which finished execution,
|
|
/// if available. (This may not be available on all platforms.)
|
|
/// \param Errors the errors from the task which finished execution, if
|
|
/// available and SeparateErrors was true. (This may not be available on all
|
|
/// platforms.)
|
|
/// \param Context the context which was passed when the task was added
|
|
///
|
|
/// \returns true if further execution of tasks should stop,
|
|
/// false if execution should continue
|
|
typedef std::function<TaskFinishedResponse(ProcessId Pid, int ReturnCode,
|
|
StringRef Output, StringRef Errors, void *Context)>
|
|
TaskFinishedCallback;
|
|
|
|
/// \brief A callback which will be executed if a task exited abnormally due
|
|
/// to a signal.
|
|
///
|
|
/// \param Pid the ProcessId of the task which exited abnormally.
|
|
/// \param ErrorMsg a string describing why the task exited abnormally. If
|
|
/// no reason could be deduced, this may be empty.
|
|
/// \param Output the output from the task which exited abnormally, if
|
|
/// available. (This may not be available on all platforms.)
|
|
/// \param Errors the errors from the task which exited abnormally, if
|
|
/// available and SeparateErrors was true. (This may not be available on all
|
|
/// platforms.)
|
|
/// \param Context the context which was passed when the task was added
|
|
/// \param Signal the terminating signal number, if available.
|
|
/// This may not be available on all platforms. If it is ever provided,
|
|
/// it should not be removed in future versions of the compiler.
|
|
///
|
|
/// \returns a TaskFinishedResponse indicating whether or not execution
|
|
/// should proceed
|
|
typedef std::function<TaskFinishedResponse(ProcessId Pid, StringRef ErrorMsg,
|
|
StringRef Output, StringRef Errors,
|
|
void *Context, Optional<int> Signal)>
|
|
TaskSignalledCallback;
|
|
#pragma clang diagnostic pop
|
|
|
|
/// \brief Indicates whether TaskQueue supports buffering output on the
|
|
/// current system.
|
|
///
|
|
/// \note If this returns false, the TaskFinishedCallback passed
|
|
/// to \ref execute will always receive an empty StringRef for output, even
|
|
/// if the task actually generated output.
|
|
static bool supportsBufferingOutput();
|
|
|
|
/// \brief Indicates whether TaskQueue supports parallel execution on the
|
|
/// current system.
|
|
static bool supportsParallelExecution();
|
|
|
|
/// \returns the maximum number of tasks which this TaskQueue will execute in
|
|
/// parallel
|
|
unsigned getNumberOfParallelTasks() const;
|
|
|
|
/// \brief Adds a task to the TaskQueue.
|
|
///
|
|
/// \param ExecPath the path to the executable which the task should execute
|
|
/// \param Args the arguments which should be passed to the task
|
|
/// \param Env the environment which should be used for the task;
|
|
/// must be null-terminated. If empty, inherits the parent's environment.
|
|
/// \param Context an optional context which will be associated with the task
|
|
/// \param SeparateErrors Controls whether error output is reported separately
|
|
virtual void addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
|
ArrayRef<const char *> Env = llvm::None,
|
|
void *Context = nullptr, bool SeparateErrors = false);
|
|
|
|
/// \brief Synchronously executes the tasks in the TaskQueue.
|
|
///
|
|
/// \param Began a callback which will be called when a task begins
|
|
/// \param Finished a callback which will be called when a task finishes
|
|
/// \param Signalled a callback which will be called if a task exited
|
|
/// abnormally due to a signal
|
|
///
|
|
/// \returns true if all tasks did not execute successfully
|
|
virtual bool
|
|
execute(TaskBeganCallback Began = TaskBeganCallback(),
|
|
TaskFinishedCallback Finished = TaskFinishedCallback(),
|
|
TaskSignalledCallback Signalled = TaskSignalledCallback());
|
|
|
|
/// Returns true if there are any tasks that have been queued but have not
|
|
/// yet been executed.
|
|
virtual bool hasRemainingTasks() {
|
|
return !QueuedTasks.empty();
|
|
}
|
|
};
|
|
|
|
/// \brief A class which simulates execution of tasks with behavior similar to
|
|
/// TaskQueue.
|
|
class DummyTaskQueue : public TaskQueue {
|
|
class DummyTask {
|
|
public:
|
|
const char *ExecPath;
|
|
ArrayRef<const char *> Args;
|
|
ArrayRef<const char *> Env;
|
|
void *Context;
|
|
bool SeparateErrors;
|
|
|
|
DummyTask(const char *ExecPath, ArrayRef<const char *> Args,
|
|
ArrayRef<const char *> Env = llvm::None, void *Context = nullptr,
|
|
bool SeparateErrors = false)
|
|
: ExecPath(ExecPath), Args(Args), Env(Env), Context(Context),
|
|
SeparateErrors(SeparateErrors) {}
|
|
};
|
|
|
|
std::queue<std::unique_ptr<DummyTask>> QueuedTasks;
|
|
|
|
public:
|
|
/// \brief Create a new DummyTaskQueue instance.
|
|
DummyTaskQueue(unsigned NumberOfParallelTasks = 0);
|
|
virtual ~DummyTaskQueue();
|
|
|
|
void addTask(const char *ExecPath, ArrayRef<const char *> Args,
|
|
ArrayRef<const char *> Env = llvm::None,
|
|
void *Context = nullptr, bool SeparateErrors = false) override;
|
|
|
|
bool
|
|
execute(TaskBeganCallback Began = TaskBeganCallback(),
|
|
TaskFinishedCallback Finished = TaskFinishedCallback(),
|
|
TaskSignalledCallback Signalled = TaskSignalledCallback()) override;
|
|
|
|
bool hasRemainingTasks() override {
|
|
// Need to override here because QueuedTasks is redeclared.
|
|
return !QueuedTasks.empty();
|
|
}
|
|
|
|
};
|
|
|
|
} // end namespace sys
|
|
} // end namespace swift
|
|
|
|
#endif // SWIFT_BASIC_TASKQUEUE_H
|