summaryrefslogtreecommitdiff
path: root/src/lib/ecore/efl_loop.eo
blob: 778a94d1861e095fd289c7ddd47ce19089940065 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import efl_types;
import eina_types;

struct Efl.Loop.Arguments {
   [[EFL loop arguments data structure]]
   argv: const(array<const(stringshare)>); [[Array with loop arguments]]
   initialization: bool; [[Set to $true when the program should initialize its internal state. This happen once per process instance.]]
}

enum Efl.Loop.Coro.Prio {
    [[Priority class for the coroutine.]]

    high = 0, [[high priority coroutine, scheduled using zero-timers (will expire as soon as possible).]]
    idle, [[low priority coroutine, scheduled when nothing else should run]]
}

function Efl.Loop.Coro.Cb {
    params {
        coro: ptr(Eina.Coro); [[The coroutine handle, used to $eina_coro_yield() and voluntarily give back control to the main loop until it's rescheduled.]]
        loop: Efl.Loop; [[The loop that schedules this coroutine.]]
    }
    return: generic_value; [[Value that will resolve the promise,
                             being delivered to the future chain
                             attached to the coroutine. Note that the
                             value will be owned by the Efl_Loop_Coro
                             and Eina_Future subsystems and will be
                             flushed (eina_value_flush()) once
                             unused. Its contents must survive the
                             function return, that is, it shouldn't
                             keep pointers to the stack.
                           ]]
}; [[Coroutine function, it will be called back from the
   coroutine environment and when executed it's guaranteed that the
   main loop will be paused, so shared resources are safe to access
   (no locks are required).

   \@note Eina_Coro may use threads, then take care to handle
   thread-local-storage (TLS) details properly, eventually you
   may consider eina_coro_hook_add() to be informed when the
   main or coroutine will exit and enter. For instance this is
   used by Efl_Object (handled transparently for the user).
   ]]


class Efl.Loop (Efl.Object)
{
   [[The Efl Main Loop

   Efl main loop provide a clean and tiny event loop library with many modules to
   do lots of convenient things for a programmer, to save time and effort. It's
   small and lean, designed to work from embedded systems all the way up to large
   and powerful multi-cpu workstations. The main loop has a number of primitives to
   be used with its main loop. It serializes all the primitives and allows for
   great responsiveness without the need for threads (or any other concurrency), but
   provide them if you need to.
   ]]
   methods {
      @property main @class {
         [[Points to the main loop instance of the application.]]
         get {}
         values {
            main_loop: Efl.Loop; [[Application main loop]]
         }
      }
      @property app_efl_version {
         [[Indicates the version of EFL with which this application was compiled.

           This might differ from @.efl_version.
         ]]
         get {}
         values {
            version: ptr(const(Efl.Version)); [[Efl version]]
         }
      }
      @property efl_version {
         [[Indicates the currently running version of EFL.

           This might differ from @.app_efl_version.
         ]]
         get {}
         values {
            version: ptr(const(Efl.Version)); [[Efl version]]
         }
      }
      iterate {
         [[Runs a single iteration of the main loop to process everything on the
         queue.]]
      }
      iterate_may_block {
         [[Runs a single iteration of the main loop to process everything on the
           queue with block/non-blocking status.]]
         return: int; [[Return from single iteration run]]
         params {
            may_block: int; [[A flag if the main loop has a possibility of blocking.]]
         }
      }
      begin {
         [[Runs the application main loop.]]
         return: ubyte; [[Value set by quit()]]
      }
      quit {
         [[Quits the main loop once all the events currently on the queue have
         been processed.]]
         params {
            @in exit_code: ubyte; [[Returned value by begin()]]
         }
      }
      @property future_scheduler {
         [[Gets the Eina_Future_Scheduler for a given mainloop.

           The Eina_Future_Scheduler returned by this function
           should be used for creating promises (eina_promise_new())
           so then can properly schedule resolve/reject events.
         ]]
         get {}
         values {
             scheduler: ptr(Eina.Future.Scheduler); [[The scheduler.]]
         }
      }
      Eina_FutureXXX_job {
         [[A future promise that will be resolved from a clean main
           loop context as soon as possible.

           This has higher priority, for low priority use
           @.Eina_FutureXXX_idle
         ]]
          return: own(ptr(Eina.Future)) /* TODO: future<void> */; [[The future handle.]]
      }
      Eina_FutureXXX_idle {
         [[A future promise that will be resolved from a clean main
           loop context as soon as the main loop is idle.

           This is a low priority version of @.Eina_FutureXXX_job
         ]]
          return: own(ptr(Eina.Future)) /* TODO: future<void> */; [[The future handle.]]
      }
      Eina_FutureXXX_timeout {
         [[A future promise that will be resolved from a clean main
           loop context after $time seconds.]]
         params {
            @in time: double; [[The time from now in second that the main loop will wait before triggering it.]]
         }
         return: own(ptr(Eina.Future)) /* future<void> */; [[The future handle.]]
      }
      coro {
          [[A future promise that will be resolved using a coroutine.

            A coroutine is a function that will be executed
            cooperatively with the main loop. The main loop will
            schedule the coroutine, explicitly giving control to it --
            by then the main loop is paused. The coroutine must then
            finish and return, or yield control back to the main loop
            using $eina_coro_yield(). This allows for shared context
            to be safely interchanged with the main loop -- it is
            guaranteed that if the coroutine is running, the main loop
            is pause; if the main loop is running the coroutine is
            paused.

            Coroutines are implemented with @Eina.Coro, see their API
            and how it's exposed in your language -- it may be the
            case that you don't need to worry and it will be managed
            transparently by your language/binding.

            Once finished the coroutine returns a value, that will be
            used to resolve the promise, propagating thru the future
            chain.
          ]]
          params {
              @in priority: Efl.Loop.Coro.Prio; [[The priority used to schedule the coroutine.]]
              @in func: Efl.Loop.Coro.Cb @nonull; [[The function to run as a coroutine.]]
          }
          return: own(ptr(Eina.Future)) /* future<> */; [[The future handle, it provides the value returned by $func once it exits.]]
      }
      job {
         [[Will execute that promise in the near future.]]
         params {
            @in data: const(void_ptr) @optional; [[The data to be given when the promise is done.]]
         }
         return: future<void_ptr>; [[The promise that will be triggered.]]
      }
      timeout {
         [[Will trigger this promise when the specified timeout occur.]]
         params {
            @in time: double; [[The time from now in second that the main loop will wait before triggering it.]]
            @in data: const(void_ptr) @optional; [[The data to be given when the promise is done.]]
         }
         return: future<void_ptr>; [[The promise that will be triggered.]]
      }
      register {
         [[Will register a manager of a specific class to be answered by eo.provider_find.]]
         params {
            @in klass: const(Efl.Class); [[The class provided by the registered provider.]]
            @in provider: const(Efl.Object); [[The provider for the newly registered class that has to provide that said Efl.Class.]]
         }
         return: bool; [[$true if successfully register, $false otherwise.]]
      }
      unregister {
         [[Will unregister a manager of a specific class that was previously registered and answered by eo.provider_find.]]
         params {
            @in klass: const(Efl.Class); [[The class provided by the provider to unregister for.]]
            @in provider: const(Efl.Object); [[The provider for the registered class to unregister.]]
         }
         return: bool; [[$true if successfully unregistered, $false otherwise.]]
      }
   }
   events {
      idle,enter @restart; [[Event occurs once the main loop enters the idle state.]]
      idle,exit @restart; [[Event occurs once the main loop exits the idle state.]]
      idle @restart; [[Event occurs once the main loop is idler. Be carefull, this will spin your CPU high if you keep listening on this event.]]
      arguments: Efl.Loop.Arguments; [[Event happens when args are provided to the loop by args_add().]]
      poll,high; [[Event occurs multiple time per second. The exact tick is undefined and could be adjusted system wide.]]
      poll,medium; [[Event occurs multiple time per minute. The exact tick is undefined and could be adjusted system wide.]]
      poll,low; [[Event occurs multiple time every 15 minutes. The exact tick is undefined and could be adjusted system wide.]]
   }
   implements {
      Efl.Object.constructor;
      Efl.Object.destructor;
      Efl.Object.provider_find;
   }
}