resize_publication.go RawHistoryFolder
1package daemon
2
3import (
4 "github.com/bnema/vev/internal/domain"
5 "github.com/bnema/vev/internal/ports"
6)
7
8type resizeCommitPublication struct {
9 members []resizeMember
10 session *session
11 attachment *attachedClient
12 lease *attachmentLease
13 epoch uint64
14 connection attachmentConnectionToken
15 coordinator *renderCoordinator
16 observer ports.RuntimeObserver
17 mark ports.RuntimeMark
18}
19
20func (p resizeCommitPublication) current() bool {
21 if !resizeMembersOwnerCurrent(p.members) {
22 return false
23 }
24 if p.attachment == nil {
25 return true
26 }
27 // Attached resize publication is admitted only through a live attachment effect ticket.
28 if p.connection.effect == nil {
29 return false
30 }
31 if p.connection.effect.ended.Load() || p.connection.sess != p.session ||
32 p.connection.ac != p.attachment || p.connection.lease != p.lease ||
33 p.connection.generation != p.attachment.connectionGeneration.Load() ||
34 !p.attachment.transportSnapshotCurrent(p.connection.transport) ||
35 p.attachment.currentSession() != p.session || p.coordinator == nil {
36 return false
37 }
38 registered := attachmentRegistered(p.session, p.attachment)
39 return registered && p.coordinator.resizeCurrentForLease(p.epoch, p.attachment, p.lease, false)
40}
41
42// emit performs observer work only after every resize-owner fence and
43// attachment sendMu are released. The generation-bound publication is checked
44// once more so a move that wins after geometry publication but before observer
45// admission suppresses stale source telemetry.
46func (p resizeCommitPublication) emit() bool {
47 if !p.current() {
48 return false
49 }
50 if p.observer != nil {
51 p.observer.ObserveRuntime(p.mark)
52 }
53 return true
54}
55
56// publishResizeCommit linearizes attachment geometry and an immutable telemetry
57// reservation with pane ownership. sendMu is acquired before resize fences, so
58// the canonical rule never acquires an attachment lock while a pane fence is
59// held. Observer callbacks run only after both lock families are released.
60func (d *Daemon) publishResizeCommit(members []resizeMember, sess *session, ac *attachedClient, lease *attachmentLease, epoch uint64, ticket *attachmentEffectTicket, size domain.Size) bool {
61 if ac != nil && ticket == nil {
62 return false
63 }
64 d.observeBeforeResizeOwnerPostEffect(resizeOwnerPostCommitPublication)
65 if ac != nil {
66 ac.sendMu.Lock()
67 if d.afterResizeCommitSendLocked != nil {
68 d.afterResizeCommitSendLocked()
69 }
70 }
71 fences := acquireResizeOwnerPostEffectFences(members)
72 if fences == nil {
73 if ac != nil {
74 ac.sendMu.Unlock()
75 }
76 return false
77 }
78 publication := resizeCommitPublication{
79 members: append([]resizeMember(nil), members...),
80 session: sess,
81 attachment: ac,
82 lease: lease,
83 epoch: epoch,
84 observer: d.runtimeObserver,
85 mark: ports.NewRuntimeMark("daemon", ports.RuntimeResizeCommitted, 0, true),
86 }
87 if ticket != nil {
88 publication.connection = ticket.connectionToken()
89 publication.coordinator = sess.renderCoordinator()
90 }
91 if !publication.current() {
92 fences.Release()
93 if ac != nil {
94 ac.sendMu.Unlock()
95 }
96 return false
97 }
98 if ac != nil {
99 ac.setSize(size)
100 }
101 fences.Release()
102 if ac != nil {
103 ac.sendMu.Unlock()
104 }
105 return publication.emit()
106}