Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define state consistency within a revision #223

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

zetanumbers
Copy link
Contributor

@zetanumbers zetanumbers commented Dec 14, 2020

Resolves #222 #220 #215 #197.

  • Update dependencies;
  • Update documentation;
  • Create formal definition in the docs;
  • Add new "strong" tests.

@zetanumbers zetanumbers marked this pull request as ready for review December 26, 2020 15:05
@zetanumbers zetanumbers changed the title Reconsideration of the runtime logic Define state consistency within a revision Dec 28, 2020
@codecov
Copy link

codecov bot commented Dec 29, 2020

Codecov Report

Merging #223 (cfa7bec) into main (4d14a31) will decrease coverage by 0.54%.
The diff coverage is 42.36%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #223      +/-   ##
==========================================
- Coverage   27.78%   27.24%   -0.55%     
==========================================
  Files          50       50              
  Lines       11886    11729     -157     
  Branches     6634     6564      -70     
==========================================
- Hits         3303     3195     -108     
- Misses       6391     6446      +55     
+ Partials     2192     2088     -104     
Impacted Files Coverage Δ
dom/examples/todo/src/filter.rs 0.00% <ø> (ø)
dom/examples/todo/src/item.rs 23.29% <ø> (+1.04%) ⬆️
src/runtime/runloop.rs 68.42% <0.00%> (-4.92%) ⬇️
src/runtime/context.rs 37.70% <13.04%> (-18.75%) ⬇️
src/runtime/var.rs 24.13% <17.64%> (-23.49%) ⬇️
src/runtime.rs 23.67% <45.45%> (-0.77%) ⬇️
src/lib.rs 38.98% <80.00%> (-1.26%) ⬇️
mox/src/lib.rs 0.00% <0.00%> (-40.00%) ⬇️
benches/core.rs 75.00% <0.00%> (-15.00%) ⬇️
dom/examples/ssr/src/main.rs 28.81% <0.00%> (-8.48%) ⬇️
... and 14 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4d14a31...cfa7bec. Read the comment docs.

Copy link
Owner

@anp anp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry it took so long to get to this! I like this approach a lot, although I have some questions about the public API it exposes -- see my review comments.

@@ -25,6 +25,9 @@ impl super::Runtime {
where
Root: FnMut() -> Out,
{
// RunLoop always forces it's first revision?
// or maybe just check if current revision is 0
self.force();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's possible to remove the force() API, I'd prefer that. It's an additional branch at the top of each revision but I don't think this code isn't hot enough to care about that overhead.

/// Runs the root closure once with access to the runtime context, returning
/// the result. `Waker` is set for the next `Revision`, which starts after
/// the start of the run.
pub fn run_once_with(&mut self, waker: Waker) -> Out {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to make this the only API? Is there a reason we still need to cache the waker and support running without one?

/// which is probably the desired behavior if the embedding system will
/// call `Runtime::run_once` on a regular interval regardless.
pub fn set_state_change_waker(&mut self, wk: Waker) {
self.wk = wk;
pub fn set_state_change_waker(&mut self, waker: Waker) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At one point we discussed removing this altogether in favor of deleting run_once and having run_once_with take a waker -- is that still an option here?

Comment on lines +218 to +220
rcs_write.revision.0 += 1;
rcs_write.pending_changes.store(false, std::sync::atomic::Ordering::Relaxed);
drop(rcs_write);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you extract this to a separate method like RevisionController::increment_revision? It'll make calls to execute() a little more verbose but we'll never risk blocking writes to state variables if something changes here, because the write guard can't escape the controller's method body.

@@ -41,6 +43,13 @@ impl std::fmt::Debug for Revision {
}
}

#[derive(Debug)]
pub(crate) struct RevisionControlSystem {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: RevisionController

Can you move this type to another file, src/runtime/controller.rs?

Comment on lines +71 to +72
let rcs_read = self.rcs.read();
let current = rcs_read.revision;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let rcs_read = self.rcs.read();
let current = rcs_read.revision;
let current = rcs.revision();


/// Returns a reference to the current commit.
pub fn current_commit(&mut self) -> &Commit<State> {
let current = self.rcs.read().revision;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let current = self.rcs.read().revision;
let current = self.rcs.revision();

@@ -49,7 +49,7 @@ pub fn filter_link(to_set: Visibility) -> Li {
mox! {
<li>
<a style="cursor: pointer;"
class={if *visibility == to_set { "selected" } else { "" }}
class={if *visibility.commit_at_root() == to_set { "selected" } else { "" }}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need to acquire a lock here to get the visibility for the revision, but I think this is a problem for you because of my past laziness.

At the top of this function is this attribute:

#[illicit::from_env(visibility: &Key<Visibility>)]

I think this needs to become

#[illicit::from_env(visibility: &Commit<Visibility>, set_visibility: &Key<Visibility>)]

Which will require exposing the current commit via https://github.com/anp/moxie/blob/main/dom/examples/todo/src/lib.rs#L53 as well.

@@ -97,7 +97,8 @@ mod tests {
pub async fn single_item() {
let root = document().create_element("div");
crate::App::boot_fn(&[Todo::new("weeeee")], root.clone(), || {
let todo = &illicit::expect::<Key<Vec<Todo>>>()[0];
let todos_key = &illicit::expect::<Key<Vec<Todo>>>();
let todo = &todos_key.commit_at_root()[0];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to my other comment, I think we need to pass down a Commit<Vec<Todo>> from the App.

@@ -35,8 +35,8 @@ pub fn toggle(default_checked: bool) -> Span {
#[illicit::from_env(todos: &Key<Vec<Todo>>, visibility: &Key<Visibility>)]
pub fn todo_list() -> Ul {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comments in other todomvc files, I think if you add Commit<Visibility> and Commit<Vec<Todo>> to the illicit environment then you can avoid all the commit_at_root calls in this file.

@anp
Copy link
Owner

anp commented Jan 4, 2021

A question: would this change be easier if RevisionControlState used an AtomicU64 to track the revision number rather than the Revision type itself?

zetanumbers added 7 commits January 5, 2021 17:00
Removed `commit_at_root` field of the `Key` bc of it being out of date.
increments, commits from the past revisions are lazely commited at
first measurement
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ensure state consistency within a revision
2 participants