Skip to content

Commit

Permalink
Improve docs & names.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gohla committed Jan 11, 2024
1 parent bcc294e commit ff5335a
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 34 deletions.
2 changes: 1 addition & 1 deletion pie/src/context/bottom_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ impl<'p, 's> BottomUpContext<'p, 's> {

/// Schedule tasks affected by `resource`.
#[inline]
pub fn schedule_affected_by(&mut self, resource: &dyn KeyObj) {
pub fn schedule_tasks_affected_by(&mut self, resource: &dyn KeyObj) {
let track_end = self.session.tracker.schedule_affected_by_resource(resource);
let node = self.session.store.get_or_create_resource_node(resource);
for (task_node, dependency) in self.session.store.get_read_and_write_dependencies_to_resource(&node) {
Expand Down
41 changes: 25 additions & 16 deletions pie/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub trait Task: KeyBounds {
}

/// Programmatic incremental build context, enabling tasks to require other tasks and read/write from/to resources,
/// programmatically creating precise dependencies that are used to incrementally execute tasks.
/// programmatically creating precise dynamic dependencies that are used to incrementally execute tasks.
///
/// Tasks can [require](Self::require) other tasks, creating a task dependency and getting their consistent (i.e.,
/// most up-to-date) output value.
Expand Down Expand Up @@ -171,21 +171,24 @@ pub trait ResourceChecker<R: Resource>: KeyBounds {
/// Stamps `resource` with a `reader` for that resource.
///
/// The `reader` is fresh: it is first passed to this checker before being passed to a task. However, because it is
/// later passed to a task, `reader` must be _left in a fresh state after stamping_. For example, a buffered reader
/// must be rewound after using it.
/// later passed to a task, `reader` must be _left in a fresh state after stamping_. For example, a
/// [buffered reader](std::io::BufReader) must be [rewound](std::io::Seek::rewind) after using it.
fn stamp_reader(&self, resource: &R, reader: &mut R::Reader<'_>) -> Result<Self::Stamp, Self::Error>;
/// Stamps `resource` with a `writer` for that resource.
///
/// The `writer` is dirty: it was first used by a task to write data. Therefore, be sure to restore the `writer` to a
/// fresh state before reading from it. For example, a file must be rewound after using it.
/// fresh state before reading from it. For example, a [file](std::fs::File) must be [rewound](std::io::Seek::rewind)
/// before using it.
///
/// There is no guarantee that `resource` still exists, as it may have been removed by a task. Therefore, `writer` may
/// contain stale data for certain resources. If that can be the case, be sure to check whether `writer` is still
/// consistent w.r.t. `resource.
/// contain stale metadata for certain resources. For example, a [file](std::fs::File) can be
/// [removed](std::fs::remove_file), but its [file](std::fs::File) descriptor will still return cached (stale)
/// [metadata](std::fs::File::metadata). If that can be the case, be sure to check whether `writer` is still
/// consistent with `resource`.
fn stamp_writer(&self, resource: &R, writer: R::Writer<'_>) -> Result<Self::Stamp, Self::Error>;

/// Type of inconsistency used for debugging/logging purposes. The `'i` lifetime represents this checker, or the
/// resource/state/stamp passed to [Self::get_inconsistency].
/// Type of inconsistency used for debugging/logging purposes. The `'i` lifetime represents this checker and the
/// lifetime of the `resource`, `state`, and `stamp` passed to [Self::get_inconsistency].
type Inconsistency<'i>: Debug;
/// Checks whether `resource` is inconsistent w.r.t. `stamp`, with access to `state`. Returns `Some(inconsistency)`
/// when inconsistent, `None` when consistent.
Expand Down Expand Up @@ -262,28 +265,34 @@ impl<'p> Session<'p> {
self.0.require(task)
}

/// Creates a bottom-up build. Call [BottomUp::changed_resource] to schedule tasks affected by changed resources. Then
/// call [BottomUp::update_affected_tasks] to update all affected tasks in a bottom-up build.
/// Creates a bottom-up build. Call [schedule_tasks_affected_by](BottomUpBuild::schedule_tasks_affected_by) for each
/// changed resource to schedule tasks affected by changed resources.
///
/// Then call [update_affected_tasks](BottomUpBuild::update_affected_tasks) to update all affected tasks in a
/// bottom-up build.
///
/// Finally, use [require](Self::require) of this session to get up-to-date task outputs if needed.
#[inline]
#[must_use]
pub fn bottom_up_build<'s>(&'s mut self) -> BottomUp<'p, 's> {
BottomUp(self.0.bottom_up_build())
pub fn create_bottom_up_build<'s>(&'s mut self) -> BottomUpBuild<'p, 's> {
BottomUpBuild(self.0.create_bottom_up_build())
}

/// Gets all errors produced during dependency checks.
#[inline]
#[must_use]
pub fn dependency_check_errors(&self) -> impl Iterator<Item=&dyn Error> + ExactSizeIterator {
self.0.dependency_check_errors()
}
}

#[repr(transparent)]
pub struct BottomUp<'p, 's>(pie::BottomUpInternal<'p, 's>);
impl<'p, 's> BottomUp<'p, 's> {
pub struct BottomUpBuild<'p, 's>(pie::BottomUpBuildInternal<'p, 's>);
impl<'p, 's> BottomUpBuild<'p, 's> {
/// Schedule tasks affected by `resource`.
#[inline]
pub fn changed_resource(&mut self, resource: &dyn KeyObj) {
self.0.changed_resource(resource);
pub fn schedule_tasks_affected_by(&mut self, resource: &dyn KeyObj) {
self.0.schedule_tasks_affected_by(resource);
}
/// Update all tasks affected by resource changes.
#[inline]
Expand Down
14 changes: 7 additions & 7 deletions pie/src/pie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ impl<'p> SessionInternal<'p> {
}

#[inline]
pub fn bottom_up_build<'s>(&'s mut self) -> BottomUpInternal<'p, 's> {
BottomUpInternal(BottomUpContext::new(self))
pub fn create_bottom_up_build<'s>(&'s mut self) -> BottomUpBuildInternal<'p, 's> {
BottomUpBuildInternal(BottomUpContext::new(self))
}

#[inline]
Expand All @@ -92,13 +92,13 @@ impl<'p> SessionInternal<'p> {
}
}

/// Internals for [`BottomUpInternal`].
/// Internals for [`BottomUpBuildInternal`].
#[repr(transparent)]
pub struct BottomUpInternal<'p, 's>(BottomUpContext<'p, 's>);
impl<'p, 's> BottomUpInternal<'p, 's> {
pub struct BottomUpBuildInternal<'p, 's>(BottomUpContext<'p, 's>);
impl<'p, 's> BottomUpBuildInternal<'p, 's> {
#[inline]
pub fn changed_resource(&mut self, resource: &dyn KeyObj) {
self.0.schedule_affected_by(resource);
pub fn schedule_tasks_affected_by(&mut self, resource: &dyn KeyObj) {
self.0.schedule_tasks_affected_by(resource);
}
#[inline]
pub fn update_affected_tasks(mut self) {
Expand Down
14 changes: 7 additions & 7 deletions pie/tests/bottom_up.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fn test_directly_affected_task() -> TestResult {

// Change the file that the task requires, directly affecting it.
write_until_modified(&path, "hello world!")?;
pie.bottom_up_build_then_assert(|b| b.changed_resource(&path), |tracker| {
pie.bottom_up_build_then_assert(|b| b.schedule_tasks_affected_by(&path), |tracker| {
assert_matches!(tracker.first_execute_end(&task), Some(d) => {
assert_eq!(d.output.cast(), Ok("hello world!"));
});
Expand All @@ -75,7 +75,7 @@ fn test_indirectly_affected_tasks() -> TestResult {

// Change the file that ReadFile requires, directly affecting it, indirectly affecting ToLower.
write_until_modified(&path, "HELLO WORLD!!")?;
pie.bottom_up_build_then_assert(|b| b.changed_resource(&path), |tracker| {
pie.bottom_up_build_then_assert(|b| b.schedule_tasks_affected_by(&path), |tracker| {
// ReadFile
let read_task_end = assert_matches!(tracker.first_execute_end(&read_task), Some(d) => {
assert_eq!(d.output.cast(), Ok("HELLO WORLD!!"));
Expand Down Expand Up @@ -110,7 +110,7 @@ fn test_indirectly_affected_tasks_early_cutoff() -> TestResult {
// Change the file that ReadFile requires, directly affecting it, indirectly affecting ToLower, but not affecting
// WriteFile because the output from ToLower does not change.
write_until_modified(&read_path, "hello world!")?;
pie.bottom_up_build_then_assert(|b| b.changed_resource(&read_path), |tracker| {
pie.bottom_up_build_then_assert(|b| b.schedule_tasks_affected_by(&read_path), |tracker| {
// ReadFile
let read_task_end = assert_matches!(tracker.first_execute_end(&read_task), Some(d) => {
assert_eq!(d.output.cast(), Ok("hello world!"));
Expand Down Expand Up @@ -153,7 +153,7 @@ fn test_indirectly_affected_multiple_tasks() -> TestResult {
// Change the file that ReadFile requires, directly affecting it, indirectly affecting ToLower and
// ToUpper, but not their WriteFile tasks.
write_until_modified(&read_path, "hello world!")?;
pie.bottom_up_build_then_assert(|b| b.changed_resource(&read_path), |tracker| {
pie.bottom_up_build_then_assert(|b| b.schedule_tasks_affected_by(&read_path), |tracker| {
// ReadFile
let read_task_end = assert_matches!(tracker.first_execute_end(&read_task), Some(d) => {
assert_eq!(d.output.cast(), Ok("hello world!"));
Expand All @@ -179,7 +179,7 @@ fn test_indirectly_affected_multiple_tasks() -> TestResult {

// Change the file that ReadFile requires, directly affecting it, indirectly affecting all other tasks.
write_until_modified(&read_path, "hello world!!")?;
pie.bottom_up_build_then_assert(|b| b.changed_resource(&read_path), |tracker| {
pie.bottom_up_build_then_assert(|b| b.schedule_tasks_affected_by(&read_path), |tracker| {
// ReadFile
let read_task_end = assert_matches!(tracker.first_execute_end(&read_task), Some(d) => {
assert_eq!(d.output.cast(), Ok("hello world!!"));
Expand Down Expand Up @@ -253,8 +253,8 @@ fn test_require_now() -> TestResult {
// Change the file that ReadFile reads, which `to_lower_task` depends on, thus `to_lower_task` is affected and should be executed.
write_until_modified(&read_path, "hello world!!")?;
pie.bottom_up_build_then_assert(|b| {
b.changed_resource(&read_path);
b.changed_resource(&marker_path)
b.schedule_tasks_affected_by(&read_path);
b.schedule_tasks_affected_by(&marker_path)
}, |tracker| {
let task_end = assert_matches!(tracker.first_execute_end_index(&task), Some(i) => i);
let to_lower_task_end = assert_matches!(tracker.first_execute_end_index(&to_lower_task), Some(i) => i);
Expand Down
6 changes: 3 additions & 3 deletions pie/tests/util/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::io::{BufWriter, Stdout};

use pie::{BottomUp, Pie, Session, Task};
use pie::{BottomUpBuild, Pie, Session, Task};
use pie::tracker::CompositeTracker;
use pie::tracker::event::EventTracker;
use pie::tracker::writing::WritingTracker;
Expand Down Expand Up @@ -58,11 +58,11 @@ pub trait TestPieExt {

fn bottom_up_build_then_assert(
&mut self,
bottom_up_func: impl FnOnce(&mut BottomUp),
bottom_up_func: impl FnOnce(&mut BottomUpBuild),
test_assert_func: impl FnOnce(&EventTracker),
) {
self.assert_in_session(|s| {
let mut bottom_up = s.bottom_up_build();
let mut bottom_up = s.create_bottom_up_build();
bottom_up_func(&mut bottom_up);
bottom_up.update_affected_tasks();
}, test_assert_func)
Expand Down

0 comments on commit ff5335a

Please sign in to comment.