Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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 All @@ -26,6 +26,10 @@ namespace Tizen.Applications
/// <since_tizen> 3 </since_tizen>
public class TizenSynchronizationContext : SynchronizationContext
{
// Initialize() installs the context on the thread that runs the target main loop,
// so the constructing thread is the loop thread that dispatches posted callbacks.
private readonly int _loopThreadId = Environment.CurrentManagedThreadId;

/// <summary>
/// Initilizes a new TizenSynchronizationContext and install into the current thread.
/// </summary>
Expand All @@ -51,10 +55,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 +68,33 @@ 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, _loopThreadId);
}
}

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

public static void Send(SendOrPostCallback d, object state, bool useTizenGlibContext, int loopThreadId)
{
if (Environment.CurrentManagedThreadId == loopThreadId)
{
Exception err = null;
// Already on the loop thread; run inline because blocking here would
// prevent the loop from ever dispatching the posted callback.
d(state);
return;
}

using (var mre = new ManualResetEventSlim(false))
{
ExceptionDispatchInfo edi = null;
GSourceManager.Post(() =>
{
#pragma warning disable CA1031
Expand All @@ -79,19 +104,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 @@ -15,7 +15,6 @@
*/

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

Expand All @@ -28,6 +27,10 @@ namespace Tizen.Applications
[EditorBrowsable(EditorBrowsableState.Never)]
public class TizenUISynchronizationContext : SynchronizationContext
{
// Initialize() installs the context on the UI thread that runs the target main loop,
// so the constructing thread is the loop thread that dispatches posted callbacks.
private readonly int _loopThreadId = Environment.CurrentManagedThreadId;

/// <summary>
/// Initilizes a new TizenUISynchronizationContext and install into the current thread.
/// </summary>
Expand All @@ -53,10 +56,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 +69,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, _loopThreadId);
}
}
}
}
Loading