@@ -83,18 +83,54 @@ func Register(fn RunFunc) {
8383 runFunc = fn
8484}
8585
86+ // resetOutputBuf clears the shared output buffer.
87+ func resetOutputBuf () {
88+ OutputMu .Lock ()
89+ defer OutputMu .Unlock ()
90+ outputBuf .Reset ()
91+ }
92+
93+ // appendToOutputBuf writes data into the shared output buffer.
94+ func appendToOutputBuf (data []byte ) {
95+ OutputMu .Lock ()
96+ defer OutputMu .Unlock ()
97+ outputBuf .Write (data )
98+ }
99+
100+ // FormatToOutputBuf formats and writes a message into the shared output buffer.
101+ func FormatToOutputBuf (format string , args ... any ) {
102+ OutputMu .Lock ()
103+ defer OutputMu .Unlock ()
104+ fmt .Fprintf (& outputBuf , format , args ... )
105+ }
106+
107+ // snapshotOutputBuf returns a copy of the current output buffer contents.
108+ func snapshotOutputBuf () string {
109+ OutputMu .Lock ()
110+ defer OutputMu .Unlock ()
111+ return outputBuf .String ()
112+ }
113+
114+ // snapshotOutputBufIfNonEmpty returns the buffer contents and whether the
115+ // buffer was non-empty, under a single lock acquisition.
116+ func snapshotOutputBufIfNonEmpty () (text string , nonEmpty bool ) {
117+ OutputMu .Lock ()
118+ defer OutputMu .Unlock ()
119+ nonEmpty = outputBuf .Len () > 0
120+ if nonEmpty {
121+ text = outputBuf .String ()
122+ }
123+ return text , nonEmpty
124+ }
125+
86126// OnCreate is called when the NativeActivity is created.
87127func OnCreate (
88128 cvm * jni.VM ,
89129 activity * jni.Object ,
90130) {
91131 vm = cvm
92132 activityRef = activity
93- func () {
94- OutputMu .Lock ()
95- defer OutputMu .Unlock ()
96- outputBuf .Reset ()
97- }()
133+ resetOutputBuf ()
98134 exampleStarted = false
99135}
100136
@@ -117,11 +153,7 @@ func OnNativeWindowCreated(windowPtr unsafe.Pointer) {
117153 var err error
118154 needed , err = getUngrantedPermissions (env , activityRef )
119155 if err != nil {
120- func () {
121- OutputMu .Lock ()
122- defer OutputMu .Unlock ()
123- fmt .Fprintf (& outputBuf , "permissions check: %v\n " , err )
124- }()
156+ FormatToOutputBuf ("permissions check: %v\n " , err )
125157 }
126158 return nil
127159 })
@@ -151,11 +183,7 @@ func startExample() {
151183 if err := runFunc (vm , & localBuf ); err != nil {
152184 fmt .Fprintf (& localBuf , "ERROR: %v\n " , err )
153185 }
154- func () {
155- OutputMu .Lock ()
156- defer OutputMu .Unlock ()
157- outputBuf .Write (localBuf .Bytes ())
158- }()
186+ appendToOutputBuf (localBuf .Bytes ())
159187 }
160188 RenderOutput ()
161189 }()
@@ -164,11 +192,7 @@ func startExample() {
164192// RenderOutput re-renders the current output buffer to the screen.
165193// Call from background goroutines after appending to the shared buffer.
166194func RenderOutput () {
167- text := func () string {
168- OutputMu .Lock ()
169- defer OutputMu .Unlock ()
170- return outputBuf .String ()
171- }()
195+ text := snapshotOutputBuf ()
172196 if text == "" {
173197 text = "(no output)"
174198 }
@@ -177,16 +201,7 @@ func RenderOutput() {
177201
178202// OnResume is called when the activity resumes (e.g. after permission dialog).
179203func OnResume (activity * jni.Object ) {
180- hasOutput , text := func () (bool , string ) {
181- OutputMu .Lock ()
182- defer OutputMu .Unlock ()
183- has := outputBuf .Len () > 0
184- var t string
185- if has {
186- t = outputBuf .String ()
187- }
188- return has , t
189- }()
204+ text , hasOutput := snapshotOutputBufIfNonEmpty ()
190205 if nativeWindow != nil && hasOutput {
191206 renderText (text )
192207 }
0 commit comments