📄 pthread_cleanup_push.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta name="generator" content="HTML Tidy, see www.w3.org"><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"><link type="text/css" rel="stylesheet" href="style.css"><!-- Generated by The Open Group's rhtm tool v1.2.1 --><!-- Copyright (c) 2001-2004 IEEE and The Open Group, All Rights Reserved --><title>pthread_cleanup_pop</title></head><body bgcolor="white"><script type="text/javascript" language="JavaScript" src="../jscript/codes.js"></script><basefont size="3"> <a name="pthread_cleanup_pop"></a> <a name="tag_03_514"></a><!-- pthread_cleanup_pop --> <!--header start--><center><font size="2">The Open Group Base Specifications Issue 6<br>IEEE Std 1003.1, 2004 Edition<br>Copyright © 2001-2004 The IEEE and The Open Group, All Rights reserved.</font></center><!--header end--><hr size="2" noshade><h4><a name="tag_03_514_01"></a>NAME</h4><blockquote>pthread_cleanup_pop, pthread_cleanup_push - establish cancellation handlers</blockquote><h4><a name="tag_03_514_02"></a>SYNOPSIS</h4><blockquote class="synopsis"><div class="box"><code><tt><sup>[<a href="javascript:open_code('THR')">THR</a>]</sup> <img src="../images/opt-start.gif" alt="[Option Start]" border="0"> #include <<a href="../basedefs/pthread.h.html">pthread.h</a>><br><br> void pthread_cleanup_pop(int</tt> <i>execute</i><tt>);<br> void pthread_cleanup_push(void (*</tt><i>routine</i><tt>)(void*), void *</tt><i>arg</i><tt>); <img src="../images/opt-end.gif"alt="[Option End]" border="0"></tt></code></div><tt><br></tt></blockquote><h4><a name="tag_03_514_03"></a>DESCRIPTION</h4><blockquote><p>The <i>pthread_cleanup_pop</i>() function shall remove the routine at the top of the calling thread's cancellation cleanup stackand optionally invoke it (if <i>execute</i> is non-zero).</p><p>The <i>pthread_cleanup_push</i>() function shall push the specified cancellation cleanup handler <i>routine</i> onto the callingthread's cancellation cleanup stack. The cancellation cleanup handler shall be popped from the cancellation cleanup stack andinvoked with the argument <i>arg</i> when:</p><ul><li><p>The thread exits (that is, calls <a href="../functions/pthread_exit.html"><i>pthread_exit</i>()</a>).</p></li><li><p>The thread acts upon a cancellation request.</p></li><li><p>The thread calls <i>pthread_cleanup_pop</i>() with a non-zero <i>execute</i> argument.</p></li></ul><p>These functions may be implemented as macros. The application shall ensure that they appear as statements, and in pairs withinthe same lexical scope (that is, the <i>pthread_cleanup_push</i>() macro may be thought to expand to a token list whose first tokenis <tt>'{'</tt> with <i>pthread_cleanup_pop</i>() expanding to a token list whose last token is the corresponding <tt>'}'</tt>).</p><p>The effect of calling <a href="../functions/longjmp.html"><i>longjmp</i>()</a> or <a href="../functions/siglongjmp.html"><i>siglongjmp</i>()</a> is undefined if there have been any calls to <i>pthread_cleanup_push</i>()or <i>pthread_cleanup_pop</i>() made without the matching call since the jump buffer was filled. The effect of calling <a href="../functions/longjmp.html"><i>longjmp</i>()</a> or <a href="../functions/siglongjmp.html"><i>siglongjmp</i>()</a> from inside acancellation cleanup handler is also undefined unless the jump buffer was also filled in the cancellation cleanup handler.</p><p>The effect of the use of <b>return</b>, <b>break</b>, <b>continue</b>, and <b>goto</b> to prematurely leave a code blockdescribed by a pair of <i>pthread_cleanup_push</i>() and <i>pthread_cleanup_pop</i>() functions calls is undefined.</p></blockquote><h4><a name="tag_03_514_04"></a>RETURN VALUE</h4><blockquote><p>The <i>pthread_cleanup_push</i>() and <i>pthread_cleanup_pop</i>() functions shall not return a value.</p></blockquote><h4><a name="tag_03_514_05"></a>ERRORS</h4><blockquote><p>No errors are defined.</p><p>These functions shall not return an error code of [EINTR].</p></blockquote><hr><div class="box"><em>The following sections are informative.</em></div><h4><a name="tag_03_514_06"></a>EXAMPLES</h4><blockquote><p>The following is an example using thread primitives to implement a cancelable, writers-priority read-write lock:</p><pre><tt>typedef struct { pthread_mutex_t lock; pthread_cond_t rcond, wcond; int lock_count; /* < 0 .. Held by writer. */ /* > 0 .. Held by lock_count readers. */ /* = 0 .. Held by nobody. */ int waiting_writers; /* Count of waiting writers. */} rwlock;<br>voidwaiting_reader_cleanup(void *arg){ rwlock *l;<br> l = (rwlock *) arg; pthread_mutex_unlock(&l->lock);}<br>voidlock_for_read(rwlock *l){ pthread_mutex_lock(&l->lock); pthread_cleanup_push(waiting_reader_cleanup, l); while ((l->lock_count < 0) && (l->waiting_writers != 0)) pthread_cond_wait(&l->rcond, &l->lock); l->lock_count++; /* * Note the pthread_cleanup_pop executes * waiting_reader_cleanup. */ pthread_cleanup_pop(1);}<br>voidrelease_read_lock(rwlock *l){ pthread_mutex_lock(&l->lock); if (--l->lock_count == 0) pthread_cond_signal(&l->wcond); pthread_mutex_unlock(l);}<br>voidwaiting_writer_cleanup(void *arg){ rwlock *l;<br> l = (rwlock *) arg; if ((--l->waiting_writers == 0) && (l->lock_count >= 0)) { /* * This only happens if we have been canceled. */ pthread_cond_broadcast(&l->wcond);} pthread_mutex_unlock(&l->lock);}<br>voidlock_for_write(rwlock *l){ pthread_mutex_lock(&l->lock); l->waiting_writers++; pthread_cleanup_push(waiting_writer_cleanup, l); while (l->lock_count != 0) pthread_cond_wait(&l->wcond, &l->lock); l->lock_count = -1; /* * Note the pthread_cleanup_pop executes * waiting_writer_cleanup. */ pthread_cleanup_pop(1);}<br>voidrelease_write_lock(rwlock *l){ pthread_mutex_lock(&l->lock); l->lock_count = 0; if (l->waiting_writers == 0) pthread_cond_broadcast(&l->rcond) else pthread_cond_signal(&l->wcond); pthread_mutex_unlock(&l->lock);}<br>/* * This function is called to initialize the read/write lock. */voidinitialize_rwlock(rwlock *l){ pthread_mutex_init(&l->lock, pthread_mutexattr_default); pthread_cond_init(&l->wcond, pthread_condattr_default); pthread_cond_init(&l->rcond, pthread_condattr_default); l->lock_count = 0; l->waiting_writers = 0;}<br>reader_thread(){ lock_for_read(&lock); pthread_cleanup_push(release_read_lock, &lock); /* * Thread has read lock. */ pthread_cleanup_pop(1);}<br>writer_thread(){ lock_for_write(&lock); pthread_cleanup_push(release_write_lock, &lock); /* * Thread has write lock. */pthread_cleanup_pop(1);}</tt></pre></blockquote><h4><a name="tag_03_514_07"></a>APPLICATION USAGE</h4><blockquote><p>The two routines that push and pop cancellation cleanup handlers, <i>pthread_cleanup_push</i>() and<i>pthread_cleanup_pop</i>(), can be thought of as left and right parentheses. They always need to be matched.</p></blockquote><h4><a name="tag_03_514_08"></a>RATIONALE</h4><blockquote><p>The restriction that the two routines that push and pop cancellation cleanup handlers, <i>pthread_cleanup_push</i>() and<i>pthread_cleanup_pop</i>(), have to appear in the same lexical scope allows for efficient macro or compiler implementations andefficient storage management. A sample implementation of these routines as macros might look like this:</p><pre><tt>#define pthread_cleanup_push(rtn,arg) { \ struct _pthread_handler_rec __cleanup_handler, **__head; \ __cleanup_handler.rtn = rtn; \ __cleanup_handler.arg = arg; \ (void) pthread_getspecific(_pthread_handler_key, &__head); \ __cleanup_handler.next = *__head; \ *__head = &__cleanup_handler;<br>#define pthread_cleanup_pop(ex) \ *__head = __cleanup_handler.next; \ if (ex) (*__cleanup_handler.rtn)(__cleanup_handler.arg); \}</tt></pre><p>A more ambitious implementation of these routines might do even better by allowing the compiler to note that the cancellationcleanup handler is a constant and can be expanded inline.</p><p>This volume of IEEE Std 1003.1-2001 currently leaves unspecified the effect of calling <a href="../functions/longjmp.html"><i>longjmp</i>()</a> from a signal handler executing in a POSIX System Interfaces function. If animplementation wants to allow this and give the programmer reasonable behavior, the <a href="../functions/longjmp.html"><i>longjmp</i>()</a> function has to call all cancellation cleanup handlers that have been pushed butnot popped since the time <a href="../functions/setjmp.html"><i>setjmp</i>()</a> was called.</p><p>Consider a multi-threaded function called by a thread that uses signals. If a signal were delivered to a signal handler duringthe operation of <a href="../functions/qsort.html"><i>qsort</i>()</a> and that handler were to call <a href="../functions/longjmp.html"><i>longjmp</i>()</a> (which, in turn, did <i>not</i> call the cancellation cleanup handlers) the helperthreads created by the <a href="../functions/qsort.html"><i>qsort</i>()</a> function would not be canceled. Instead, they wouldcontinue to execute and write into the argument array even though the array might have been popped off the stack.</p><p>Note that the specified cleanup handling mechanism is especially tied to the C language and, while the requirement for a uniformmechanism for expressing cleanup is language-independent, the mechanism used in other languages may be quite different. Inaddition, this mechanism is really only necessary due to the lack of a real exception mechanism in the C language, which would bethe ideal solution.</p><p>There is no notion of a cancellation cleanup-safe function. If an application has no cancellation points in its signal handlers,blocks any signal whose handler may have cancellation points while calling async-unsafe functions, or disables cancellation whilecalling async-unsafe functions, all functions may be safely called from cancellation cleanup routines.</p></blockquote><h4><a name="tag_03_514_09"></a>FUTURE DIRECTIONS</h4><blockquote><p>None.</p></blockquote><h4><a name="tag_03_514_10"></a>SEE ALSO</h4><blockquote><p><a href="pthread_cancel.html"><i>pthread_cancel</i>()</a>, <a href="pthread_setcancelstate.html"><i>pthread_setcancelstate</i>()</a>, the Base Definitions volume of IEEE Std 1003.1-2001,<a href="../basedefs/pthread.h.html"><i><pthread.h></i></a></p></blockquote><h4><a name="tag_03_514_11"></a>CHANGE HISTORY</h4><blockquote><p>First released in Issue 5. Included for alignment with the POSIX Threads Extension.</p></blockquote><h4><a name="tag_03_514_12"></a>Issue 6</h4><blockquote><p>The <i>pthread_cleanup_pop</i>() and <i>pthread_cleanup_push</i>() functions are marked as part of the Threads option.</p><p>The APPLICATION USAGE section is added.</p><p>The DESCRIPTION is updated to avoid use of the term "must" for application requirements.</p><p>IEEE Std 1003.1-2001/Cor 2-2004, item XSH/TC2/D6/88 is applied, updating the DESCRIPTION to describe theconsequences of prematurely leaving a code block defined by the <i>pthread_cleanup_push</i>() and <i>pthread_cleanup_pop</i>()functions.</p></blockquote><div class="box"><em>End of informative text.</em></div><hr size="2" noshade><center><font size="2"><!--footer start-->UNIX ® is a registered Trademark of The Open Group.<br>POSIX ® is a registered Trademark of The IEEE.<br>[ <a href="../mindex.html">Main Index</a> | <a href="../basedefs/contents.html">XBD</a> | <a href="../utilities/contents.html">XCU</a> | <a href="../functions/contents.html">XSH</a> | <a href="../xrat/contents.html">XRAT</a>]</font></center><!--footer end--><hr size="2" noshade></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -