Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

using System;
using System.Collections.Concurrent;
using System.Runtime.ExceptionServices;
using System.Threading;

namespace Tizen.Applications
Expand Down Expand Up @@ -51,10 +51,7 @@ public static void Initialize()
/// <since_tizen> 3 </since_tizen>
public override void Post(SendOrPostCallback d, object state)
{
GSourceManager.Post(() =>
{
d(state);
});
SynchronizationContextDispatcher.Post(d, state, useTizenGlibContext: false);
}

/// <summary>
Expand All @@ -67,9 +64,25 @@ public override void Post(SendOrPostCallback d, object state)
/// <since_tizen> 3 </since_tizen>
public override void Send(SendOrPostCallback d, object state)
{
using (var mre = new ManualResetEvent(false))
SynchronizationContextDispatcher.Send(d, state, useTizenGlibContext: false);
}
}

internal static class SynchronizationContextDispatcher
{
public static void Post(SendOrPostCallback d, object state, bool useTizenGlibContext)
{
GSourceManager.Post(() =>
{
Exception err = null;
d(state);
}, useTizenGlibContext);
}

public static void Send(SendOrPostCallback d, object state, bool useTizenGlibContext)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🤖 [AI Review]
🟡 Suggestion: Send still deadlocks when called from the main-loop thread itself — the posted callback can never run while mre.Wait() blocks the loop (pre-existing, but now fixable in one place thanks to this centralization). WinForms/WPF contexts invoke the delegate inline in that case; doing the same here needs reliable main-thread identification, e.g. capturing the thread ID when the context is installed:

if (Environment.CurrentManagedThreadId == s_mainThreadId)
{
    d(state); // already on the loop thread; run inline instead of blocking on our own queue
    return;
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

🤖 [AI Review]
Addressed in 0d4f958. Each context captures its installing thread's ID (per-instance rather than a single static, since TizenSynchronizationContext and TizenUISynchronizationContext dispatch to different loop threads), and Send now runs the delegate inline when already on that thread.

{
using (var mre = new ManualResetEventSlim(false))
{
ExceptionDispatchInfo edi = null;
GSourceManager.Post(() =>
{
#pragma warning disable CA1031
Expand All @@ -79,19 +92,16 @@ public override void Send(SendOrPostCallback d, object state)
}
catch (Exception ex)
{
err = ex;
edi = ExceptionDispatchInfo.Capture(ex);
}
finally
{
mre.Set();
}
#pragma warning restore CA1031
});
mre.WaitOne();
if (err != null)
{
throw err;
}
}, useTizenGlibContext);
mre.Wait();
edi?.Throw();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
* limitations under the License.
*/

using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Threading;

Expand Down Expand Up @@ -53,10 +51,7 @@ public static void Initialize()
/// <since_tizen> 10 </since_tizen>
public override void Post(SendOrPostCallback d, object state)
{
GSourceManager.Post(() =>
{
d(state);
}, true);
SynchronizationContextDispatcher.Post(d, state, useTizenGlibContext: true);
}

/// <summary>
Expand All @@ -69,32 +64,7 @@ public override void Post(SendOrPostCallback d, object state)
/// <since_tizen> 10 </since_tizen>
public override void Send(SendOrPostCallback d, object state)
{
using (var mre = new ManualResetEvent(false))
{
Exception err = null;
GSourceManager.Post(() =>
{
#pragma warning disable CA1031
try
{
d(state);
}
catch (Exception ex)
{
err = ex;
}
finally
{
mre.Set();
}
#pragma warning restore CA1031
}, true);
mre.WaitOne();
if (err != null)
{
throw err;
}
}
SynchronizationContextDispatcher.Send(d, state, useTizenGlibContext: true);
}
}
}
}
Loading