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