.\" -*- coding: UTF-8 -*- '\" t .\" Copyright, the authors of the Linux man-pages project .\" .\" SPDX-License-Identifier: Linux-man-pages-copyleft .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH pthread_cleanup_push 3 "20 أغسطس 2025" "صفحات دليل لينكس 6.18" .SH الاسم pthread_cleanup_push, pthread_cleanup_pop \- دفع وسحب معالجات تنظيف إلغاء الخيط .SH المكتبة مكتبة مسالك POSIX (\fIlibpthread\fP،\ \fI\-lpthread\fP) .SH موجز .nf \fB#include \fP .P \fBvoid pthread_cleanup_push(typeof(void (void *)) *\fP\fIroutine\fP\fB, void *\fP\fIarg\fP\fB);\fP \fBvoid pthread_cleanup_pop(int \fP\fIexecute\fP\fB);\fP .fi .SH الوصف تتعامل هذه الدوال مع كومة معالجات تنظيف إلغاء الخيط للخيط المستدعي. معالج التنظيف هو دالة تُنفذ آليًا عند إلغاء خيط (أو في ظروف أخرى متنوعة موصوفة أدناه)؛ قد يقوم، على سبيل المثال، بفتح قفل كائن المزامنة (mutex) ليصبح متاحًا لخيوط أخرى في العملية. .P تدفع الدالة \fBpthread_cleanup_push\fP() الروتين \fIroutine\fP إلى أعلى كومة معالجات التنظيف. عندما يُستدعى \fIroutine\fP لاحقًا، سيُعطى \fIarg\fP كمعامل له. .P تزيل الدالة \fBpthread_cleanup_pop\fP() الروتين الموجود في أعلى كومة معالجات التنظيف، وتنفذه اختياريًا إذا كان \fIexecute\fP غير صفري. .P يُسحب معالج تنظيف الإلغاء من الكومة ويُنفذ في الظروف التالية: .IP \[bu] 3 عند إلغاء خيط، تُسحب جميع معالجات التنظيف المكدسة وتُنفذ بترتيب عكسي للترتيب الذي دُفعت به إلى الكومة. .IP \[bu] عند إنهاء خيط باستدعاء \fBpthread_exit\fP(3)، تُنفذ جميع معالجات التنظيف كما هو موصوف في النقطة السابقة. (لا تُستدعى معالجات التنظيف إذا أنهى الخيط بتنفيذ \fIreturn\fP من دالة بدء الخيط.) .IP \[bu] عندما يستدعي خيط \fBpthread_cleanup_pop\fP() بمعامل \fIexecute\fP غير صفري، يُسحب معالج التنظيف الأعلى ويُنفذ. .P يسمح POSIX.1 بتنفيذ \fBpthread_cleanup_push\fP() و \fBpthread_cleanup_pop\fP() كوحدات ماكرو تتوسع إلى نص يحتوي على \[aq]\fB{\fP\[aq] و \[aq]\fB}\fP\[aq]، على التوالي. لهذا السبب، يجب على المستدعي ضمان أن استدعاءات هذه الدوال مقترنة داخل نفس الدالة، وعلى نفس مستوى التداخل المعجمي. (بمعنى آخر، يُنشأ معالج التنظيف فقط أثناء تنفيذ قسم محدد من الكود.) .P استدعاء \fBlongjmp\fP(3) (\fBsiglongjmp\fP(3)) يُنتج نتائج غير محددة إذا تم أي استدعاء لـ \fBpthread_cleanup_push\fP() أو \fBpthread_cleanup_pop\fP() دون الاستدعاء المطابق للزوج منذ أن مُلئ مخزن القفز بواسطة \fBsetjmp\fP(3) (\fBsigsetjmp\fP(3)). وبالمثل، استدعاء \fBlongjmp\fP(3) (\fBsiglongjmp\fP(3)) من داخل معالج تنظيف يُنتج نتائج غير محددة ما لم يُملأ مخزن القفز أيضًا بواسطة \fBsetjmp\fP(3) (\fBsigsetjmp\fP(3)) داخل المعالج. .SH "قيمة الإرجاع" لا تعيد هذه الدوال قيمة. .SH الأخطاء لا توجد أخطاء. .SH السمات للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر \fBattributes\fP(7). .TS allbox; lbx lb lb l l l. الواجهة السمة القيمة T{ .na .nh \fBpthread_cleanup_push\fP(), \fBpthread_cleanup_pop\fP() T} سلامة الخيوط MT\-Safe .TE .SH الإصدارات في glibc، الدالتان \fBpthread_cleanup_push\fP() و \fBpthread_cleanup_pop\fP() \fIهما\fP منفذتان كوحدات ماكرو تتوسع إلى نص يحتوي على \[aq]\fB{\fP\[aq] و \[aq]\fB}\fP\[aq]، على التوالي. هذا يعني أن المتغيرات المعلنة ضمن نطاق الاستدعاءات المقترنة لهذه الدوال ستكون مرئية فقط ضمن ذلك النطاق. .P .\" The text was actually added in the 2004 TC2 يقول POSIX.1 أن تأثير استخدام \fIreturn\fP أو \fIbreak\fP أو \fIcontinue\fP أو \fIgoto\fP لمغادرة كتلة محصورة بين \fBpthread_cleanup_push\fP() و \fBpthread_cleanup_pop\fP() مبكرًا هو غير محدد. يجب على التطبيقات المحمولة تجنب فعل ذلك. .SH المعايير POSIX.1\-2008. .SH التاريخ POSIX.1\-2001. glibc 2.0. .SH أمثلة يقدم البرنامج أدناه مثالًا بسيطًا لاستخدام الدوال الموصوفة في هذه الصفحة. ينشئ البرنامج خيطًا ينفذ حلقة محصورة بين \fBpthread_cleanup_push\fP() و \fBpthread_cleanup_pop\fP(). تزيد هذه الحلقة متغيرًا عامًا، \fIcnt\fP، مرة كل ثانية. اعتمادًا على وسائط سطر الأوامر المقدمة، يرسل الخيط الرئيسي للخيط الآخر طلب إلغاء، أو يضبط متغيرًا عامًا يتسبب في خروج الخيط الآخر من حلقته وإنهائه بشكل طبيعي (عن طريق تنفيذ \fIreturn\fP). .P في جلسة الصدفة التالية، يرسل الخيط الرئيسي طلب إلغاء إلى الخيط الآخر: .P .in +4n .EX $\fB ./a.out\fP; New thread started cnt = 0 cnt = 1 Canceling thread Called clean\-up handler Thread was canceled; cnt = 0 .EE .in .P مما سبق، نرى أن الخيط أُلغي، وأن معالج تنظيف الإلغاء استُدعي وأعاد ضبط قيمة المتغير العام \fIcnt\fP إلى 0. .P في التشغيل التالي، يضبط البرنامج الرئيس متغيرًا عامًا يتسبب في إنهاء الخيط الآخر بشكل طبيعي: .P .in +4n .EX $\fB ./a.out x\fP; New thread started cnt = 0 cnt = 1 Thread terminated normally; cnt = 2 .EE .in .P مما سبق، نرى أن معالج التنظيف لم يُنفذ (لأن \fIcleanup_pop_arg\fP كانت 0)، وبالتالي لم تُعد قيمة \fIcnt\fP. .P في التشغيل التالي، يضبط البرنامج الرئيس متغيرًا عامًا يتسبب في إنهاء الخيط الآخر بشكل طبيعي، ويوفر قيمة غير صفرية لـ \fIcleanup_pop_arg\fP: .P .in +4n .EX $\fB ./a.out x 1\fP; New thread started cnt = 0 cnt = 1 Called clean\-up handler Thread terminated normally; cnt = 0 .EE .in .P في المثال أعلاه، نرى أنه على الرغم من أن الخيط لم يُلغَ، فقد نُفذ معالج التنظيف، لأن الوسيط المُعطى لـ \fBpthread_cleanup_pop\fP() كان غير صفري. .SS "مصدر البرنامج" .\" SRC BEGIN (pthread_cleanup_push.c) \& .EX #include #include #include #include #include #include #include \& static int done = 0; static int cleanup_pop_arg = 0; static int cnt = 0; \& static void cleanup_handler(void *arg) { printf("Called clean\-up handler\[rs]n"); cnt = 0; } \& static void * thread_start(void *arg) { time_t curr; \& printf("New thread started\[rs]n"); \& pthread_cleanup_push(cleanup_handler, NULL); \& curr = time(NULL); \& while (!done) { pthread_testcancel(); /* A cancelation point */ if (curr < time(NULL)) { curr = time(NULL); printf("cnt = %d\[rs]n", cnt); /* A cancelation point */ cnt++; } } \& pthread_cleanup_pop(cleanup_pop_arg); return NULL; } \& int main(int argc, char *argv[]) { pthread_t thr; int s; void *res; \& s = pthread_create(&thr, NULL, thread_start, NULL); if (s != 0) errc(EXIT_FAILURE, s, "pthread_create"); \& sleep(2); /* Allow new thread to run a while */ \& if (argc > 1) { if (argc > 2) cleanup_pop_arg = atoi(argv[2]); done = 1; \& } else { printf("Canceling thread\[rs]n"); s = pthread_cancel(thr); if (s != 0) errc(EXIT_FAILURE, s, "pthread_cancel"); } \& s = pthread_join(thr, &res); if (s != 0) errc(EXIT_FAILURE, s, "pthread_join"); \& if (res == PTHREAD_CANCELED) printf("Thread was canceled; cnt = %d\[rs]n", cnt); else printf("Thread terminated normally; cnt = %d\[rs]n", cnt); exit(EXIT_SUCCESS); } .EE .\" SRC END .SH "انظر أيضًا" \fBpthread_cancel\fP(3)، \fBpthread_cleanup_push_defer_np\fP(3)، \fBpthread_setcancelstate\fP(3)، \fBpthread_testcancel\fP(3)، \fBpthreads\fP(7) .PP .SH ترجمة تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي . .PP هذه الترجمة هي وثيقة مجانية؛ راجع .UR https://www.gnu.org/licenses/gpl-3.0.html رخصة جنو العامة الإصدار 3 .UE أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات. .PP إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: .MT kde-l10n-ar@kde.org .ME .