Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ElmSharp] Question about EcoreSynchronizationContext.Post() #694

Closed
ppaneksamsung opened this issue Jan 29, 2019 · 3 comments · Fixed by #695
Closed

[ElmSharp] Question about EcoreSynchronizationContext.Post() #694

ppaneksamsung opened this issue Jan 29, 2019 · 3 comments · Fixed by #695

Comments

@ppaneksamsung
Copy link

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?

@myroot
Copy link
Contributor

myroot commented Jan 29, 2019

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

@ppaneksamsung
Copy link
Author

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.

@myroot
Copy link
Contributor

myroot commented Oct 16, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants