Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.Common / Tizen.Applications / TizenSynchronizationContext.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Collections.Concurrent;
19 using System.Threading;
20
21 namespace Tizen.Applications
22 {
23
24     /// <summary>
25     /// Provides a synchronization context for the Tizen application model.
26     /// </summary>
27     public class TizenSynchronizationContext : SynchronizationContext
28     {
29         private readonly Interop.Glib.GSourceFunc _wrapperHandler;
30         private readonly Object _transactionLock = new Object();
31         private readonly ConcurrentDictionary<int, Action> _handlerMap = new ConcurrentDictionary<int, Action>();
32         private int _transactionId = 0;
33
34         /// <summary>
35         /// Initializes a new instance of the TizenSynchronizationContext class.
36         /// </summary>
37         public TizenSynchronizationContext()
38         {
39             _wrapperHandler = new Interop.Glib.GSourceFunc(Handler);
40         }
41
42         /// <summary>
43         /// Initilizes a new TizenSynchronizationContext and install into current thread
44         /// </summary>
45         /// <remarks>
46         /// It is equivalent
47         /// <code>
48         /// SetSynchronizationContext(new TizenSynchronizationContext());
49         /// </code>
50         /// </remarks>
51         public static void Initialize()
52         {
53             SetSynchronizationContext(new TizenSynchronizationContext());
54         }
55
56
57         /// <summary>
58         /// Dispatches an asynchronous message to a Tizen main loop.
59         /// </summary>
60         /// <param name="d"><see cref="System.Threading.SendOrPostCallback"/>The SendOrPostCallback delegate to call.</param>
61         /// <param name="state"><see cref="System.Object"/>The object passed to the delegate.</param>
62         /// <remarks>
63         /// The Post method starts an asynchronous request to post a message.</remarks>
64         public override void Post(SendOrPostCallback d, object state)
65         {
66             Post(() =>
67             {
68                 d(state);
69             });
70         }
71
72         /// <summary>
73         /// Dispatches a synchronous message to a Tizen main loop
74         /// </summary>
75         /// <param name="d"><see cref="System.Threading.SendOrPostCallback"/>The SendOrPostCallback delegate to call.</param>
76         /// <param name="state"><see cref="System.Object"/>The object passed to the delegate.</param>
77         /// <remarks>
78         /// The Send method starts a synchronous request to send a message.</remarks>
79         public override void Send(SendOrPostCallback d, object state)
80         {
81             var mre = new ManualResetEvent(false);
82             Exception err = null;
83             Post(() =>
84             {
85                 try
86                 {
87                     d(state);
88                 }
89                 catch (Exception ex)
90                 {
91                     err = ex;
92                 }
93                 finally
94                 {
95                     mre.Set();
96                 }
97             });
98             mre.WaitOne();
99             if (err != null)
100             {
101                 throw err;
102             }
103         }
104
105         private void Post(Action action)
106         {
107             int id = 0;
108             lock (_transactionLock)
109             {
110                 id = _transactionId++;
111             }
112             _handlerMap.TryAdd(id, action);
113             Interop.Glib.IdleAdd(_wrapperHandler, (IntPtr)id);
114         }
115
116         private bool Handler(IntPtr userData)
117         {
118             int key = (int)userData;
119             if (_handlerMap.ContainsKey(key))
120             {
121                 Action action;
122                 _handlerMap.TryRemove(key, out action);
123                 action?.Invoke();
124             }
125             return false;
126         }
127     }
128 }