1 /* EINA - EFL data type library 2 * Copyright (C) 2012 Cedric Bail 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; 16 * if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifndef EINA_THREAD_H_ 20 #define EINA_THREAD_H_ 21 22 #include "eina_config.h" 23 #include "eina_types.h" 24 #include "eina_error.h" 25 26 #include <stdint.h> 27 28 /** 29 * @defgroup Eina_Thread_Group Thread 30 * @ingroup Eina_Tools_Group 31 * 32 * Abstracts platform threads, providing a uniform API. It's modeled 33 * after POSIX THREADS (pthreads), on Linux they are almost 1:1 34 * mapping. 35 * 36 * @see @ref Eina_Lock_Group for mutex/locking abstraction. 37 * 38 * @since 1.8 39 * @{ 40 */ 41 42 /** 43 * @typedef Eina_Thread 44 * Type for a generic thread. 45 */ 46 typedef uintptr_t Eina_Thread; 47 48 /** 49 * @typedef Eina_Thread_Cb 50 * Type for the definition of a thread callback function 51 */ 52 typedef void *(*Eina_Thread_Cb)(void *data, Eina_Thread t); 53 54 /** 55 * @typedef Eina_Thread_Priority 56 * Type to enumerate different thread priorities 57 */ 58 typedef enum _Eina_Thread_Priority 59 { 60 EINA_THREAD_URGENT, /**< Higher than average process priority */ 61 EINA_THREAD_NORMAL, /**< Standard process priority */ 62 EINA_THREAD_BACKGROUND, /**< Lower than average process priority */ 63 EINA_THREAD_IDLE /**< Thread to be executed only when the processor is idle */ 64 } Eina_Thread_Priority; 65 66 /** 67 * @brief Returns identifier of the current thread. 68 * @return identifier of current thread. 69 * @since 1.8 70 */ 71 EAPI Eina_Thread eina_thread_self(void) EINA_WARN_UNUSED_RESULT; 72 73 /** 74 * @brief Checks if two thread identifiers are the same. 75 * @param[in] t1 first thread identifier to compare. 76 * @param[in] t2 second thread identifier to compare. 77 * @return #EINA_TRUE if they are equal, #EINA_FALSE otherwise. 78 * @since 1.8 79 */ 80 EAPI Eina_Bool eina_thread_equal(Eina_Thread t1, Eina_Thread t2) EINA_WARN_UNUSED_RESULT; 81 82 /** 83 * @brief Creates a new thread, setting its priority and affinity. 84 * 85 * @param[out] t where to return the thread identifier. Must @b not be @c NULL. 86 * @param[in] prio thread priority to use, usually EINA_THREAD_BACKGROUND 87 * @param[in] affinity thread affinity to use. To not set affinity use @c -1. 88 * @param[in] func function to run in the thread. Must @b not be @c NULL. 89 * @param[in] data context data to provide to @a func as first argument. 90 * @return #EINA_TRUE if thread was created, #EINA_FALSE on errors. 91 * @since 1.8 92 */ 93 EAPI Eina_Bool eina_thread_create(Eina_Thread *t, 94 Eina_Thread_Priority prio, int affinity, 95 Eina_Thread_Cb func, const void *data) EINA_ARG_NONNULL(1, 4) EINA_WARN_UNUSED_RESULT; 96 97 /** 98 * @brief The return value of eina_thread_join() if it was canceled with 99 * eina_thread_cancel(). 100 * 101 * A thread must be explicitly flagged as cancellable with 102 * eina_thread_cancellable_set(), by default it's not and this value 103 * shouldn't be returned. 104 * 105 * @see eina_thread_join() 106 * 107 * @since 1.19 108 */ 109 EAPI extern const void *EINA_THREAD_JOIN_CANCELED; 110 111 /** 112 * @brief Joins a currently running thread, waiting until it finishes. 113 * 114 * This function will block the current thread until @a t 115 * finishes. The returned value is the one returned by @a t @c func() 116 * and may be @c NULL on errors. See @ref Eina_Error_Group to identify 117 * problems. 118 * 119 * @param[in] t thread identifier to wait. 120 * @return value returned by @a t creation function @c func() or 121 * @c NULL on errors. Check error with @ref Eina_Error_Group. 122 * If the thread was canceled, it will return 123 * EINA_THREAD_JOIN_CANCELED. 124 * @since 1.8 125 */ 126 EAPI void *eina_thread_join(Eina_Thread t); 127 128 /** 129 * @brief Sets the name of a given thread for debugging purposes. 130 * 131 * This maps to the pthread_setname_np() GNU extension or similar 132 * if available. The name may be limited in size (possibly 16 133 * characters including the null byte terminator). This is useful 134 * for debugging to name a thread so external tools can display a 135 * meaningful name attached to the thread. 136 * 137 * @param[in] t thread to set the name of 138 * @param[in] name a string to name the thread - this cannot be NULL 139 * @return EINA_TRUE if it succeeds in setting the name or EINA_FALSE 140 * otherwise. 141 * @since 1.16 142 */ 143 EAPI Eina_Bool eina_thread_name_set(Eina_Thread t, const char *name); 144 145 /** 146 * @brief Attempts to cancel a running thread. 147 * 148 * This function sends a cancellation request to the thread, however 149 * that request is only fulfilled if the thread is cancellable 150 * (eina_thread_cancellable_set() with EINA_TRUE as first parameter) 151 * and it will wait for a cancellation point, be 152 * eina_thread_cancel_checkpoint() or some syscall as defined in 153 * man:pthreads(7). 154 * 155 * A thread that was canceled will return EINA_THREAD_JOIN_CANCELED 156 * when eina_thread_join() is called. 157 * 158 * @param[in] t Thread to cancel. 159 * 160 * @return EINA_FALSE if thread was not running, EINA_TRUE 161 * otherwise. Note that if a thread is not cancellable and it 162 * is running, this function will return EINA_TRUE! 163 * 164 * @since 1.19 165 */ 166 EAPI Eina_Bool eina_thread_cancel(Eina_Thread t); 167 168 /** 169 * @brief Enables or disables if the current thread can be canceled. 170 * 171 * By default eina_thread_create() will return a thread with 172 * cancellation disabled. One can enable the cancellation by using 173 * EINA_TRUE in @a cancellable. 174 * 175 * Eina threads follow pthread_setcanceltype() 176 * PTHREAD_CANCEL_DEFERRED, that is, the actual termination will wait 177 * for a cancellation point, usually a syscall defined in 178 * man:pthreads(7) or an explicit cancellation point defined with 179 * eina_thread_cancel_checkpoint(). 180 * 181 * In order to provide cleanup around critical blocks use 182 * EINA_THREAD_CLEANUP_PUSH() and EINA_THREAD_CLEANUP_POP() macros 183 * (which maps to pthread_cleanup_push() and pthread_cleanup_pop()), 184 * or the helper function eina_thread_cancellable_run() which does the 185 * pair for you. 186 * 187 * @param[in] cancellable If EINA_TRUE, this thread will be accept 188 * cancellation requests. If EINA_FALSE -- the default, it will 189 * ignore cancellation requests. 190 * @param[in] was_cancellable If non-NULL, will return the previous state, 191 * shall you want to restore. 192 * 193 * @return EINA_TRUE if it succeeds in setting the cancellable state 194 * or EINA_FALSE otherwise. 195 * 196 * @see eina_thread_cancel_checkpoint() 197 * @see EINA_THREAD_CLEANUP_PUSH() 198 * @see EINA_THREAD_CLEANUP_POP() 199 * @see eina_thread_cancellable_run() 200 * @see eina_thread_cancel() 201 * 202 * @since 1.19 203 */ 204 EAPI Eina_Bool eina_thread_cancellable_set(Eina_Bool cancellable, Eina_Bool *was_cancellable); 205 206 /** 207 * If the current thread is cancellable, this introduces a 208 * cancellation check point. Otherwise it's a no-operation. 209 * 210 * Eina threads follow pthread_setcanceltype() 211 * PTHREAD_CANCEL_DEFERRED, that is, the actual termination will wait 212 * for a cancellation point, usually a syscall defined in 213 * man:pthreads(7) or an explicit cancellation point defined with this 214 * function. 215 * 216 * @see eina_thread_cancel_checkpoint() 217 * 218 * @since 1.19 219 */ 220 EAPI void eina_thread_cancel_checkpoint(void); 221 222 /** 223 * @def EINA_THREAD_CLEANUP_PUSH(cleanup, data) 224 * 225 * @brief Pushes a cleanup function to be executed when the thread is 226 * canceled. 227 * 228 * This macro will schedule a function cleanup(data) to be executed if 229 * the thread is canceled with eina_thread_cancel() and the thread 230 * was previously marked as cancellable with 231 * eina_thread_cancellable_set(). 232 * 233 * It @b must be paired with EINA_THREAD_CLEANUP_POP() in the same 234 * code block as they will expand to do {} while ()! 235 * 236 * The cleanup function may also be executed if 237 * EINA_THREAD_CLEANUP_POP(EINA_TRUE) is used. 238 * 239 * @note If the block within EINA_THREAD_CLEANUP_PUSH() and 240 * EINA_THREAD_CLEANUP_POP() returns, the cleanup callback will 241 * @b not be executed! To avoid problems prefer to use 242 * eina_thread_cancellable_run()! 243 * 244 * @param[in] cleanup The function to execute on cancellation. 245 * @param[in] data The context to give to cleanup function. 246 * 247 * @see eina_thread_cancellable_run() 248 * 249 * @since 1.19 250 */ 251 #define EINA_THREAD_CLEANUP_PUSH(cleanup, data) \ 252 pthread_cleanup_push(cleanup, data) 253 254 /** 255 * @def EINA_THREAD_CLEANUP_POP(exec_cleanup) 256 * 257 * @brief Pops a cleanup function to be executed when the thread is 258 * canceled. 259 * 260 * This macro will remove a previously pushed cleanup function, thus 261 * if the thread is canceled with eina_thread_cancel() and the thread 262 * was previously marked as cancellable with 263 * eina_thread_cancellable_set(), that cleanup won't be executed 264 * anymore. 265 * 266 * It @b must be paired with EINA_THREAD_CLEANUP_PUSH() in the same 267 * code block as they will expand to do {} while ()! 268 * 269 * @note If the block within EINA_THREAD_CLEANUP_PUSH() and 270 * EINA_THREAD_CLEANUP_POP() returns, the cleanup callback will 271 * @b not be executed even if exec_cleanup is EINA_TRUE! To 272 * avoid problems prefer to use eina_thread_cancellable_run()! 273 * 274 * @param[in] exec_cleanup if EINA_TRUE, the function registered with 275 * EINA_THREAD_CLEANUP_PUSH() will be executed. 276 * 277 * @see eina_thread_cancellable_run() 278 * 279 * @since 1.19 280 */ 281 #define EINA_THREAD_CLEANUP_POP(exec_cleanup) \ 282 pthread_cleanup_pop(exec_cleanup) 283 284 /** 285 * @typedef Eina_Thread_Cancellable_Run_Cb 286 * Type for the definition of a cancellable callback to run. 287 * 288 * @since 1.19 289 */ 290 typedef void *(*Eina_Thread_Cancellable_Run_Cb)(void *data); 291 292 /** 293 * This function will setup cleanup callback, turn the thread 294 * cancellable, execute the given callback, reset the cancellable 295 * state to its old value, run the cleanup callback and then return 296 * the callback return value. 297 * 298 * @note cleanup_cb is configured @b before the thread is made 299 * cancellable, thus it @b will be executed while @a cb may not 300 * in the case the thread was already canceled and that was 301 * pending. 302 * 303 * This helper does exactly the following code. Should you need a 304 * slightly different behavior, use the base calls yourself. 305 * 306 * @code 307 * Eina_Bool old = EINA_FALSE; 308 * void *ret; 309 * 310 * EINA_THREAD_CLEANUP_PUSH(cleanup_cb, data); 311 * eina_thread_cancellable_set(EINA_TRUE, &old); // is a cancellation point 312 * ret = cb(data); // may not run if was previously canceled 313 * EINA_THREAD_CLEANUP_POP(EINA_TRUE); 314 * eina_thread_cancellable_set(old, NULL); 315 * return ret; 316 * @endcode 317 * 318 * @param[in] cb a cancellable callback to possibly run. The callback @b 319 * may not be executed if the thread had a pending cancellation 320 * request. During its execution the callback may be canceled 321 * at explicit cancellation points using 322 * eina_thread_cancel_checkpoint(), as well as some syscalls 323 * defined in man:pthreads(7). 324 * @param[in] cleanup_cb a cleanup callback to be executed regardless of 325 * the thread being canceled or not. This function will be 326 * executed even if @a cb wasn't. 327 * @param[in] data context to give to both @a cb and @a cleanup_cb. 328 * 329 * @return the return value of @a cb. If the thread was canceled, 330 * this function will not return. 331 * 332 * @since 1.19 333 */ 334 EAPI void *eina_thread_cancellable_run(Eina_Thread_Cancellable_Run_Cb cb, Eina_Free_Cb cleanup_cb, void *data); 335 336 /** 337 * @} 338 */ 339 340 #endif 341