[NUI] TCSACR-226 code change (#1032)
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / EcoreMainloop.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
20 namespace ElmSharp
21 {
22     /// <summary>
23     /// EcoreMainloop is a helper class, which provides the functions relative to Ecore's main loop.
24     /// </summary>
25     /// <since_tizen> preview </since_tizen>
26     public static class EcoreMainloop
27     {
28
29         static readonly ConcurrentDictionary<int, Func<bool>> _taskMap = new ConcurrentDictionary<int, Func<bool>>();
30         static readonly Object _taskLock = new Object();
31         static int _newTaskId = 0;
32
33         static Interop.Ecore.EcoreTaskCallback _nativeHandler;
34
35         static EcoreMainloop()
36         {
37             Interop.Ecore.ecore_init();
38             Interop.Ecore.ecore_main_loop_glib_integrate();
39             _nativeHandler = NativeHandler;
40         }
41
42         /// <summary>
43         /// Checks if you are calling this function from the main thread.
44         /// </summary>
45         /// <remarks>True if the calling function is the same thread, false otherwise.</remarks>
46         /// <since_tizen> preview </since_tizen>
47         public static bool IsMainThread => Interop.Eina.eina_main_loop_is();
48
49         /// <summary>
50         /// Runs the application main loop.
51         /// </summary>
52         /// <since_tizen> preview </since_tizen>
53         public static void Begin()
54         {
55             Interop.Ecore.ecore_main_loop_begin();
56         }
57
58         /// <summary>
59         /// Quits the main loop, once all the events currently on the queue have been processed.
60         /// </summary>
61         /// <since_tizen> preview </since_tizen>
62         public static void Quit()
63         {
64             Interop.Ecore.ecore_main_loop_quit();
65         }
66
67         /// <summary>
68         /// Adds an idler handler.
69         /// </summary>
70         /// <param name="task">The action to call when idle.</param>
71         /// <since_tizen> preview </since_tizen>
72         public static void Post(Action task)
73         {
74             int id = RegistHandler(() => { task(); return false; });
75             Interop.Ecore.ecore_idler_add(_nativeHandler, (IntPtr)id);
76         }
77
78         /// <summary>
79         /// Calls the callback asynchronously in the main loop.
80         /// </summary>
81         /// <param name="task">The action wanted to be called.</param>
82         /// <since_tizen> preview </since_tizen>
83         public static void PostAndWakeUp(Action task)
84         {
85             if (IsMainThread)
86             {
87                 Post(task);
88             }
89             else
90             {
91                 int id = RegistHandler(() => { task(); return false; });
92                 Interop.Ecore.ecore_main_loop_thread_safe_call_async(_nativeHandler, (IntPtr)id);
93             }
94         }
95
96         /// <summary>
97         /// Calls the callback synchronously in the main loop.
98         /// </summary>
99         /// <param name="task">The action wanted to be called.</param>
100         /// <since_tizen> preview </since_tizen>
101         public static void Send(Action task)
102         {
103             int id = RegistHandler(() => { task(); return false; });
104             Interop.Ecore.ecore_main_loop_thread_safe_call_sync(_nativeHandler, (IntPtr)id);
105         }
106
107         /// <summary>
108         /// Creates a timer to call the given function in the given period of time.
109         /// </summary>
110         /// <param name="interval">The interval in seconds.</param>
111         /// <param name="handler">The given function.</param>
112         /// <returns>A timer object handler on success, or null on failure.</returns>
113         /// <since_tizen> preview </since_tizen>
114         public static IntPtr AddTimer(double interval, Func<bool> handler)
115         {
116             int id = RegistHandler(handler);
117             return Interop.Ecore.ecore_timer_add(interval, _nativeHandler, (IntPtr)id);
118         }
119
120         /// <summary>
121         /// Removes the specified timer from the timer list.
122         /// </summary>
123         /// <param name="id">The specified timer handler</param>
124         /// <since_tizen> preview </since_tizen>
125         public static void RemoveTimer(IntPtr id)
126         {
127             int taskId = (int)Interop.Ecore.ecore_timer_del(id);
128             Func<bool> unused;
129             _taskMap.TryRemove(taskId, out unused);
130         }
131
132         static int RegistHandler(Func<bool> task)
133         {
134             int taskId;
135             lock (_taskLock)
136             {
137                 taskId = _newTaskId++;
138             }
139             _taskMap[taskId] = task;
140             return taskId;
141         }
142
143         static bool NativeHandler(IntPtr user_data)
144         {
145             int task_id = (int)user_data;
146             Func<bool> userAction = null;
147             if (_taskMap.TryGetValue(task_id, out userAction))
148             {
149                 bool result = false;
150
151                 if (userAction != null)
152                 {
153                     result = userAction();
154                 }
155
156                 if (!result)
157                 {
158                     _taskMap.TryRemove(task_id, out userAction);
159                 }
160                 return result;
161             }
162             return false;
163         }
164     }
165 }