Samsung / TizenFX

C# Device APIs for Tizen

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[ElmSharp] Question about EcoreSynchronizationContext.Post()

ppaneksamsung opened this issue · comments

Hello,

I have a question regarding the EcoreSynchronizationContext.Post() method. According to the documentation, this method should dispatch an asynchronous message to a main loop, see:

    /// <summary>
    /// Dispatches an asynchronous message to a Ecore main loop.
    /// </summary>
    /// <param name="d"><see cref="T:System.Threading.SendOrPostCallback" />The SendOrPostCallback delegate to call.</param>
    /// <param name="state"><see cref="T:System.Object" />The object passed to the delegate.</param>
    /// <remarks>The Post method starts an asynchronous request to post a message.</remarks>
    /// <since_tizen> preview </since_tizen>
    public override void Post(SendOrPostCallback d, object state);

I would expect that my message will be added to the end of a main loop queue and called when all pending messages are processed. This would be consistent with other SynchronizationContext implementations, like: TizenSynchronizationContext or Nito.AsyncEx.AsyncContext.AsyncContextSynchronizationContext. However, EcoreSynchronizationContext behaves differently - a message is called synchronously if it is dispatched on a main loop thread, see:

EAPI void
ecore_main_loop_thread_safe_call_async(Ecore_Cb callback,
                                       void    *data)
{
   Ecore_Safe_Call *order;

   if (!callback) return;

   if (eina_main_loop_is())
     {
        callback(data);
        return;
     }

Such behavior may cause reentrancy issues and it seems to be inconsistent with the documentation. Is it intentional?

Yes, you're right.
It should be called idle step on main loop iteration.
I also expected ecore_main_loop_safe_call_async working as asynchronous but does not

Fortunately, EcoreSynchronizationContext is not used in normal case.
Instead TizenSynchronizationContext is used

If you need a Post behavior on your application, You can use EcoreMainloop.Post method

Anyway, I'll fix it

Thanks your reports

Hello,

Your change fixes the reported problem, however it introduces another one. Basically, the documentation doesn't mention anything about call order, but some applications expect that:

EcoreMainLoop.Post(action1);
EcoreMainLoop.Post(action2);

will result that action1 will be called before action2. That's not true for Post method (and PostAndWakeUp called on the main thread). Please check following snippet:

for (var i = 0; i < 10; ++i)
{
  var val = i;
  EcoreMainloop.PostAndWakeUp(() => { Log.Info("LoopTest", $"{val}"); });
}

When called on the main thread, it prints:

I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 9
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 8
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 7
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 6
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 5
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 4
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 3
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 2
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 1
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(61) > 0

When called on a non-main thread, it prints:

I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 0
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 1
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 2
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 3
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 4
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 5
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 6
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 7
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 8
I/LoopTest(10974): XamarinPlayer.Tizen.cs: OnCreate(70) > 9

Example when such behavior causes a problem can be found here:
https://github.com/Samsung/react-native-tizen-dotnet/blob/master/Framework/ReactNet/ReactNativeTizen/DevSupport/DevOptionDialog.cs
The line 92 is executed after 46.

As you mentioned, Post method does not guarantee the order of call.
Our implementation is depend on EFL. So behavior of API also same with EFL
And Post method implemented with ecore_idler_add. ecore_idler_add also does not guaranteed