Setting since_tizen 3/4 on Tizen.NET API
[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     /// <since_tizen> 3 </since_tizen>
28     public class TizenSynchronizationContext : SynchronizationContext
29     {
30         private readonly Interop.Glib.GSourceFunc _wrapperHandler;
31         private readonly Object _transactionLock = new Object();
32         private readonly ConcurrentDictionary<int, Action> _handlerMap = new ConcurrentDictionary<int, Action>();
33         private int _transactionId = 0;
34
35         /// <summary>
36         /// Initializes a new instance of the TizenSynchronizationContext class.
37         /// </summary>
38         /// <since_tizen> 3 </since_tizen>
39         public TizenSynchronizationContext()
40         {
41             _wrapperHandler = new Interop.Glib.GSourceFunc(Handler);
42         }
43
44         /// <summary>
45         /// Initilizes a new TizenSynchronizationContext and install into the current thread.
46         /// </summary>
47         /// <remarks>
48         /// It is equivalent.
49         /// <code>
50         /// SetSynchronizationContext(new TizenSynchronizationContext());
51         /// </code>
52         /// </remarks>
53         /// <since_tizen> 3 </since_tizen>
54         public static void Initialize()
55         {
56             SetSynchronizationContext(new TizenSynchronizationContext());
57         }
58
59
60         /// <summary>
61         /// Dispatches an asynchronous message to a Tizen main loop.
62         /// </summary>
63         /// <param name="d"><see cref="System.Threading.SendOrPostCallback"/>The SendOrPostCallback delegate to call.</param>
64         /// <param name="state"><see cref="System.Object"/>The object passed to the delegate.</param>
65         /// <remarks>
66         /// The post method starts an asynchronous request to post a message.</remarks>
67         /// <since_tizen> 3 </since_tizen>
68         public override void Post(SendOrPostCallback d, object state)
69         {
70             Post(() =>
71             {
72                 d(state);
73             });
74         }
75
76         /// <summary>
77         /// Dispatches a synchronous message to a Tizen main loop.
78         /// </summary>
79         /// <param name="d"><see cref="System.Threading.SendOrPostCallback"/>The SendOrPostCallback delegate to call.</param>
80         /// <param name="state"><see cref="System.Object"/>The object passed to the delegate.</param>
81         /// <remarks>
82         /// The send method starts a synchronous request to send a message.</remarks>
83         /// <since_tizen> 3 </since_tizen>
84         public override void Send(SendOrPostCallback d, object state)
85         {
86             var mre = new ManualResetEvent(false);
87             Exception err = null;
88             Post(() =>
89             {
90                 try
91                 {
92                     d(state);
93                 }
94                 catch (Exception ex)
95                 {
96                     err = ex;
97                 }
98                 finally
99                 {
100                     mre.Set();
101                 }
102             });
103             mre.WaitOne();
104             if (err != null)
105             {
106                 throw err;
107             }
108         }
109
110         private void Post(Action action)
111         {
112             int id = 0;
113             lock (_transactionLock)
114             {
115                 id = _transactionId++;
116             }
117             _handlerMap.TryAdd(id, action);
118             Interop.Glib.IdleAdd(_wrapperHandler, (IntPtr)id);
119         }
120
121         private bool Handler(IntPtr userData)
122         {
123             int key = (int)userData;
124             if (_handlerMap.ContainsKey(key))
125             {
126                 Action action;
127                 _handlerMap.TryRemove(key, out action);
128                 action?.Invoke();
129             }
130             return false;
131         }
132     }
133 }