?? threads.sgml
字號:
</informalexample></para><para>is equivalent to calling </para><para><informalexample><programlisting>return retval;</programlisting></informalexample></para><para>in the function @func, as given to g_thread_create().</para><note><para>Never call g_thread_exit() from within a thread of a #GThreadPool, asthat will mess up the bookkeeping and lead to funny and unwanted results.</para></note>@retval: the return value of this thread.<!-- ##### FUNCTION g_thread_foreach ##### --><para></para>@thread_func: @user_data: <!-- ##### STRUCT GMutex ##### --><para>The #GMutex struct is an opaque data structure to represent a mutex(mutual exclusion). It can be used to protect data against sharedaccess. Take for example the following function:<example><title>A function which will not work in a threaded environment</title><programlisting> int give_me_next_number (<!-- -->) { static int current_number = 0; /* now do a very complicated calculation to calculate the new number, this might for example be a random number generator */ current_number = calc_next_number (current_number); return current_number; }</programlisting></example></para><para>It is easy to see that this won't work in a multi-threadedapplication. There current_number must be protected against sharedaccess. A first naive implementation would be:</para><para><example><title>The wrong way to write a thread-safe function</title><programlisting> int give_me_next_number (<!-- -->) { static int current_number = 0; int ret_val; static GMutex * mutex = NULL; if (!mutex) mutex = g_mutex_new (<!-- -->); g_mutex_lock (mutex); ret_val = current_number = calc_next_number (current_number); g_mutex_unlock (mutex); return ret_val; }</programlisting></example></para><para>This looks like it would work, but there is a race condition whileconstructing the mutex and this code cannot work reliable. Please donot use such constructs in your own programs! One working solution is:</para><para><example><title>A correct thread-safe function</title><programlisting> static GMutex *give_me_next_number_mutex = NULL; /* this function must be called before any call to give_me_next_number (<!-- -->) it must be called exactly once. */ void init_give_me_next_number (<!-- -->) { g_assert (give_me_next_number_mutex == NULL); give_me_next_number_mutex = g_mutex_new (<!-- -->); } int give_me_next_number (<!-- -->) { static int current_number = 0; int ret_val; g_mutex_lock (give_me_next_number_mutex); ret_val = current_number = calc_next_number (current_number); g_mutex_unlock (give_me_next_number_mutex); return ret_val; }</programlisting></example></para><para>#GStaticMutex provides a simpler and safer way of doing this.</para><para>If you want to use a mutex, and your code should also work withoutcalling g_thread_init() first, then you can not use a #GMutex, asg_mutex_new() requires that the thread system be initialized. Use a#GStaticMutex instead.</para><para>A #GMutex should only be accessed via the following functions.</para><note><para>All of the <function>g_mutex_*</function> functions are actually macros. Apart from taking their addresses, you can however use them as if they were functions.</para></note><!-- ##### FUNCTION g_mutex_new ##### --><para>Creates a new #GMutex. </para><note><para>This function will abort if g_thread_init() has not been called yet.</para></note>@Returns: a new #GMutex.<!-- ##### FUNCTION g_mutex_lock ##### --><para>Locks @mutex. If @mutex is already locked by another thread, thecurrent thread will block until @mutex is unlocked by the otherthread.</para><para>This function can be used even if g_thread_init() has not yet beencalled, and, in that case, will do nothing.</para><note><para>#GMutex is neither guaranteed to be recursive nor to be non-recursive,i.e. a thread could deadlock while calling g_mutex_lock(), if italready has locked @mutex. Use #GStaticRecMutex, if you need recursivemutexes.</para></note>@mutex: a #GMutex.<!-- ##### FUNCTION g_mutex_trylock ##### --><para>Tries to lock @mutex. If @mutex is already locked by anotherthread, it immediately returns %FALSE. Otherwise it locks @mutexand returns %TRUE.</para><para>This function can be used even if g_thread_init() has not yet beencalled, and, in that case, will immediately return %TRUE.</para><note><para>#GMutex is neither guaranteed to be recursive nor to be non-recursive,i.e. the return value of g_mutex_trylock() could be both %FALSE or%TRUE, if the current thread already has locked @mutex. Use#GStaticRecMutex, if you need recursive mutexes.</para></note>@mutex: a #GMutex.@Returns: %TRUE, if @mutex could be locked.<!-- ##### FUNCTION g_mutex_unlock ##### --><para>Unlocks @mutex. If another thread is blocked in a g_mutex_lock() callfor @mutex, it will be woken and can lock @mutex itself.</para><para>This function can be used even if g_thread_init() has not yet beencalled, and, in that case, will do nothing.</para>@mutex: a #GMutex.<!-- ##### FUNCTION g_mutex_free ##### --><para>Destroys @mutex.</para>@mutex: a #GMutex.<!-- ##### STRUCT GStaticMutex ##### --><para>A #GStaticMutex works like a #GMutex, but it has one significantadvantage. It doesn't need to be created at run-time like a #GMutex,but can be defined at compile-time. Here is a shorter, easier andsafer version of our <function>give_me_next_number()</function> example:</para><para><example><title>Using <structname>GStaticMutex</structname> to simplify thread-safe programming</title><programlisting> int give_me_next_number (<!-- -->) { static int current_number = 0; int ret_val; static GStaticMutex mutex = G_STATIC_MUTEX_INIT; g_static_mutex_lock (&mutex); ret_val = current_number = calc_next_number (current_number); g_static_mutex_unlock (&mutex); return ret_val; }</programlisting></example></para><para>Sometimes you would like to dynamically create a mutex. If you don'twant to require prior calling to g_thread_init(), because your codeshould also be usable in non-threaded programs, you are not able touse g_mutex_new() and thus #GMutex, as that requires a prior call tog_thread_init(). In theses cases you can also use a #GStaticMutex. Itmust be initialized with g_static_mutex_init() before using it andfreed with with g_static_mutex_free() when not needed anymore to freeup any allocated resources.</para><para>Even though #GStaticMutex is not opaque, it should only be used withthe following functions, as it is defined differently on differentplatforms.</para><para>All of the <function>g_static_mutex_*</function> functions can also be used even if g_thread_init() has not yet been called.</para><note><para>All of the <function>g_static_mutex_*</function> functions are actually macros. Apart from taking their addresses, you can however use them as if they were functions.</para></note><!-- ##### MACRO G_STATIC_MUTEX_INIT ##### --><para>A #GStaticMutex must be initialized with this macro, before it can beused. This macro can used be to initialize a variable, but it cannotbe assigned to a variable. In that case you have to useg_static_mutex_init().</para><para><informalexample><programlisting>GStaticMutex my_mutex = G_STATIC_MUTEX_INIT;</programlisting></informalexample></para><!-- ##### FUNCTION g_static_mutex_init ##### --><para>Initializes @mutex. Alternatively you can initialize it with#G_STATIC_MUTEX_INIT.</para>@mutex: a #GStaticMutex to be initialized.<!-- ##### FUNCTION g_static_mutex_lock ##### --><para>Works like g_mutex_lock(), but for a #GStaticMutex.</para>@mutex: a #GStaticMutex.<!-- ##### FUNCTION g_static_mutex_trylock ##### --><para>Works like g_mutex_trylock(), but for a #GStaticMutex.</para>@mutex: a #GStaticMutex.@Returns: %TRUE, if the #GStaticMutex could be locked.<!-- ##### FUNCTION g_static_mutex_unlock ##### --><para>Works like g_mutex_unlock(), but for a #GStaticMutex.</para>@mutex: a #GStaticMutex.<!-- ##### FUNCTION g_static_mutex_get_mutex ##### --><para>For some operations (like g_cond_wait()) you must have a #GMutexinstead of a #GStaticMutex. This function will return thecorresponding #GMutex for @mutex.</para>@mutex: a #GStaticMutex.@Returns: the #GMutex corresponding to @mutex.<!-- ##### FUNCTION g_static_mutex_free ##### --><para>Releases all resources allocated to @mutex. </para><para>You don't have to call this functions for a #GStaticMutex with anunbounded lifetime, i.e. objects declared 'static', but if you have a#GStaticMutex as a member of a structure and the structure is freed,you should also free the #GStaticMutex.</para>@mutex: a #GStaticMutex to be freed.<!-- ##### MACRO G_LOCK_DEFINE ##### --><para>The %G_LOCK_* macros provide a convenient interface to #GStaticMutexwith the advantage that they will expand to nothing in programscompiled against a thread-disabled GLib, saving code and memorythere. #G_LOCK_DEFINE defines a lock. It can appear anywhere variabledefinitions may appear in programs, i.e. in the first block of afunction or outside of functions. The @name parameter will be mangledto get the name of the #GStaticMutex. This means that you can usenames of existing variables as the parameter - e.g. the name of thevariable you intent to protect with the lock. Look at our<function>give_me_next_number()</function> example using the %G_LOCK_* macros:</para><para><example><title>Using the %G_LOCK_* convenience macros</title><programlisting>G_LOCK_DEFINE (current_number);int give_me_next_number (<!-- -->) { static int current_number = 0; int ret_val; G_LOCK (current_number); ret_val = current_number = calc_next_number (current_number); G_UNLOCK (current_number); return ret_val; }</programlisting></example></para>@name: the name of the lock.<!-- ##### MACRO G_LOCK_DEFINE_STATIC ##### --><para>This works like #G_LOCK_DEFINE, but it creates a static object.</para>@name: the name of the lock.<!-- ##### MACRO G_LOCK_EXTERN ##### --><para>This declares a lock, that is defined with #G_LOCK_DEFINE in another module.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -