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

Eventually consistent tree #1281

Merged
merged 7 commits into from
Jun 27, 2024
Merged

Eventually consistent tree #1281

merged 7 commits into from
Jun 27, 2024

Conversation

yshui
Copy link
Owner

@yshui yshui commented Jun 26, 2024

... read the commit messages, i am tired.

Copy link

codecov bot commented Jun 26, 2024

Codecov Report

Attention: Patch coverage is 71.39175% with 111 lines in your changes missing coverage. Please review.

Project coverage is 52.21%. Comparing base (843f308) to head (f126d47).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             next    #1281      +/-   ##
==========================================
+ Coverage   52.03%   52.21%   +0.17%     
==========================================
  Files          64       64              
  Lines       13609    13771     +162     
==========================================
+ Hits         7081     7190     +109     
- Misses       6528     6581      +53     
Files Coverage Δ
src/c2.c 57.09% <100.00%> (ø)
src/wm/wm.h 100.00% <ø> (ø)
src/wm/wm_internal.h 100.00% <100.00%> (ø)
src/wm/win.c 71.22% <0.00%> (ø)
src/wm/tree.c 87.61% <96.36%> (-0.31%) ⬇️
src/picom.c 63.31% <66.66%> (-0.10%) ⬇️
src/x.h 77.77% <33.33%> (-7.08%) ⬇️
src/event.c 65.12% <20.00%> (-4.85%) ⬇️
src/inspect.c 0.00% <0.00%> (ø)
src/wm/wm.c 85.41% <82.00%> (+6.01%) ⬆️
... and 1 more

... and 3 files with indirect coverage changes

@yshui yshui force-pushed the eventually-consistent-tree branch 7 times, most recently from 6cbd94e to f65cbf1 Compare June 27, 2024 12:29
Why do we need this? This is because, firstly, in the X protocol,
events, errors, and replies are in a single stream to begin with, so it's
not "unnatural" to put them back. And, some replies have to be handled
in the correct "context".

Say, the X window tree look like this:

   A
  / \
 B   C

`C` is the new window, so send a query tree request for it, and you
receive:

> Event: Reparent B to C
> Query tree reply: C has child B

(Remember events, and replies are all in a single stream)

If you handle the reply before the event, which is what will happen
if you do `xcb_query_tree_reply(c, xcb_query_tree(c, ..))`, you will
think window `B` appeared in 2 places.

Also with this change the `x_handle_error` in `ev_handle` is move
into `x_poll_for_event`. It just makes more sense to there.

Signed-off-by: Yuxuan Shui <[email protected]>
wm_tree_new_window is splitted into 3 steps: creating the window object
(wm_tree_new_window), adding it to the hash table (wm_tree_add_window),
and attaching it to its parent (wm_tree_attach).

wm_tree_reparent is splitted into wm_tree_detach and then
wm_tree_attach.

Signed-off-by: Yuxuan Shui <[email protected]>
If a toplevel is reparented, then destroy, any WM_TREE_CHANGE_CLIENT
events currently queued will reference the freed toplevel node.

Note this doesn't happen when the toplevel is destroyed directly.
Because in that case it will be turned into a zombie, and is guaranteed
to only be freed after the client change event is handled.

With this commit, when a toplevel is killed (i.e. destroyed or
reparented), all currently queued tree changes will be updated to
reference the zombie instead.

Signed-off-by: Yuxuan Shui <[email protected]>
This is part of the effort to remove reliance on the X critical section
for internal consistency. The rational will be explained in later
commits when it is complete.

Instead of using server grabbing to guarantee that our tree is
synchronized with the X server, this commit moves the wm tree to an
"eventually consistent" model, utilizing the newly introduced async X
request infrastructure (See commit: "x: add support for receiving
replies as part of the event stream").

The algorithm is like this: let's look at each tree node individually,
every node has a list of children. If this list consistent with the X
server for each of the tree nodes, the entire tree is consistent.

Let's also define a "partial consistency" concept. A tree is partially
consistent, if for all the nodes in the tree, their lists of chilren are
either consistent, or empty. Meaning some nodes might exist on the X
server, but not replicated on our side. If a node's parent isn't in our
tree, we call that node "orphaned". (Conveniently, a toplevel can never
be orphaned, because the root window is always in the tree.)

To achieve partial consistency, when each node is discovered (either via
a CreateNotify from the server, or via a QueryTree request, you will see
later), we set up an  event mask  on it to  receive further updates, and
then send a QueryTree request for it. The trick is that the reply to the
QueryTree request will  be processed in order with all the other events,
errors and replies. Assuming the tree started out  partially consistent,
it  will still be  partially  consistent  after we processed  the reply.
Because the  reply contains  up-to-date information about  that  node at
that point  in time;  and we have  also processed  all events  that came
before that reply,  so all other nodes are consistent too. Further more,
the tree will  stay partially  consistent, because the event mask we set
up will keep  bringing us new information for the newly discovered node.

This partial consistency will eventually become full consistency after
all of our requests to the X server have completed.

Note this means we might start rendering with a partial window tree. In
practice, that should hardly be noticeable.

(The explanation above glossed over many implementation concerns, some
of those are documentation in code comments.)

Signed-off-by: Yuxuan Shui <[email protected]>
@yshui yshui force-pushed the eventually-consistent-tree branch from f65cbf1 to f126d47 Compare June 27, 2024 13:10
@yshui yshui merged commit d383dd2 into next Jun 27, 2024
18 checks passed
@yshui yshui deleted the eventually-consistent-tree branch June 27, 2024 15:42
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.

1 participant