وضعیت‌های نخ و قفل مفسر سراسری

مگر در free-threaded build از CPython، مفسر پایتون به‌طور کلی نخ‌ایمن نیست. به منظور پشتیبانی از برنامه‌های چندنخی پایتون، یک قفل سراسری به نام global interpreter lock یا GIL وجود دارد که باید پیش از دسترسی به اشیای پایتون، توسط یک نخ نگه داشته شود. بدون این قفل، حتی ساده‌ترین عملیات‌ها می‌توانند در یک برنامه‌ی چندنخی مشکل ایجاد کنند: برای مثال، وقتی دو نخ هم‌زمان شمارش ارجاع یک شیء واحد را افزایش می‌دهند، ممکن است شمارش ارجاع در نهایت به جای دو بار، فقط یک بار افزایش یابد.

از این رو، تنها نخی که قفل مفسر سراسری (GIL) را در اختیار دارد، می‌تواند روی اشیای پایتون عمل کند یا C API پایتون را فراخوانی کند.

برای شبیه‌سازی همزمانی، مفسر به‌طور منظم تلاش می‌کند نخ‌ها را بین دستورالعمل‌های بایت‌کد تعویض کند (به sys.setswitchinterval() مراجعه کنید). به همین دلیل است که قفل‌ها برای نخ‌ایمنی در کد پایتون خالص نیز ضروری هستند.

علاوه بر این، قفل مفسر سراسری در اطراف عملیات ورودی/خروجی (I/O) مسدودکننده، مانند خواندن از یک پرونده یا نوشتن در آن، آزاد می‌شود. از طریق C API، این کار با جدا کردن وضعیت نخ انجام می‌شود.

مفسر پایتون برخی از اطلاعات نخ‌محلی را درون ساختار داده‌ای به نام PyThreadState نگه می‌دارد که به آن وضعیت نخ گفته می‌شود. هر نخ یک اشاره‌گر نخ‌محلی به یک PyThreadState دارد؛ وضعیت نخی که این اشاره‌گر به آن ارجاع می‌دهد، متصل در نظر گرفته می‌شود.

یک نخ در هر لحظه تنها می‌تواند یک attached thread state داشته باشد. وضعیت نخ متصل معمولاً معادل با در اختیار داشتن GIL است، به‌جز در ساخت‌های نخ‌آزاد. در ساخت‌هایی که GIL فعال است، متصل کردن یک وضعیت نخ تا زمانی که بتوان GIL را به دست آورد، مسدود می‌ماند. با این حال، حتی در ساخت‌هایی که GIL غیرفعال است، همچنان داشتن یک وضعیت نخ متصل الزامی است، زیرا مفسر باید پیگیری کند که کدام نخ‌ها ممکن است به اشیای پایتون دسترسی داشته باشند.

نکته

حتی در ساخت‌ نخ‌آزاد، پیوست کردن وضعیت نخ ممکن است مسدود شود، زیرا قفل مفسر سراسری می‌تواند دوباره فعال شود یا نخ‌ها ممکن است به‌طور موقت معلق شوند (مانند هنگام زباله‌روبی).

به‌طور کلی، هنگام استفاده از API زبان C پایتون، همیشه یک وضعیت نخ متصل وجود خواهد داشت، از جمله در حین تعبیه و هنگام پیاده‌سازی متدها؛ بنابراین به‌ندرت پیش می‌آید که لازم باشد خودتان وضعیت نخ ایجاد کنید. تنها در برخی موارد خاص، مانند داخل بلوک Py_BEGIN_ALLOW_THREADS یا در یک نخ تازه، نخ وضعیت نخ متصل نخواهد داشت. اگر مطمئن نیستید، بررسی کنید که آیا PyThreadState_GetUnchecked() مقدار NULL برمی‌گرداند یا خیر.

اگر مشخص شد که واقعاً به ایجاد یک وضعیت نخ نیاز دارید، توصیه می‌شود از PyThreadState_Ensure() یا PyThreadState_EnsureFromView() استفاده کنید، که وضعیت نخ را برای شما مدیریت خواهند کرد.

جدا کردن وضعیت نخ از کد توسعه‌ای

بیشتر کدهای توسعه‌ای که وضعیت نخ را دستکاری می‌کنند، ساختار ساده‌ی زیر را دارند:

وضعیت نخ را در یک متغیر محلی ذخیره کنید.
... یک عملیات ورودی/خروجی مسدودکننده انجام دهید ...
وضعیت نخ را از متغیر محلی بازیابی کنید.

این چنان رایج است که جفتی از ماکروها برای ساده‌سازی آن وجود دارد:

Py_BEGIN_ALLOW_THREADS
... یک عملیات ورودی/خروجی مسدودکننده انجام دهید ...
Py_END_ALLOW_THREADS

ماکروی Py_BEGIN_ALLOW_THREADS یک بلوک جدید باز می‌کند و یک متغیر محلی پنهان اعلان می‌کند؛ ماکروی Py_END_ALLOW_THREADS بلوک را می‌بندد.

بلوک بالا به کد زیر بسط می‌یابد:

PyThreadState *_save;

_save = PyEval_SaveThread();
... یک عملیات ورودی/خروجی مسدودکننده انجام دهید ...
PyEval_RestoreThread(_save);

نحوه کار این توابع به این صورت است:

متصل بودن وضعیت نخ نشان می‌دهد که قفل مفسر سراسری (GIL) برای مفسر نگه داشته شده است. برای جدا کردن آن، PyEval_SaveThread() فراخوانی می‌شود و نتیجه در یک متغیر محلی ذخیره می‌شود.

با جدا کردن وضعیت نخ، قفل مفسر سراسری (GIL) آزاد می‌شود که به نخ‌های دیگر اجازه می‌دهد در حالی که نخ فعلی در حال انجام عملیات ورودی/خروجی مسدودکننده است، به مفسر متصل شده و اجرا شوند. هنگامی که عملیات ورودی/خروجی به پایان رسید، وضعیت نخ قبلی با فراخوانی PyEval_RestoreThread() دوباره متصل می‌شود؛ این تابع تا زمانی که بتوان قفل مفسر سراسری را به دست آورد، منتظر می‌ماند.

نکته

انجام عملیات ورودی/خروجی مسدودکننده رایج‌ترین مورد استفاده برای جداسازی وضعیت نخ است، اما فراخوانی آن روی کد بومی طولانی‌مدتی که نیازی به دسترسی به اشیاء پایتون یا C API پایتون ندارد نیز مفید است. برای مثال، ماژول‌های استاندارد zlib و hashlib هنگام فشرده‌سازی یا هش کردن داده‌ها، وضعیت نخ را جدا می‌کنند.

در یک ساخت‌ نخ‌آزاد، قفل مفسر سراسری (GIL) معمولاً منتفی است، اما جدا کردن وضعیت نخ همچنان الزامی است، زیرا مفسر به‌طور دوره‌ای نیاز دارد همه‌ی نخ‌ها را مسدود کند تا نمای سازگار از اشیای پایتون را بدون خطر شرایط رقابتی به دست آورد. برای مثال، سی‌پایتون در حال حاضر هنگام اجرای زباله‌روب، همه‌ی نخ‌ها را برای مدت کوتاهی معلق می‌کند.

هشدار

جدا کردن وضعیت نخ می‌تواند در حین نهایی‌سازی مفسر به رفتار غیرمنتظره منجر شود. برای جزئیات بیشتر به احتیاط‌های مربوط به نهایی‌سازی مفسر مراجعه کنید.

APIها

ماکروهای زیر معمولاً بدون نقطه‌ویرگول انتهایی استفاده می‌شوند؛ نمونه‌های استفاده را در توزیع کد منبع پایتون جست‌وجو کنید.

نکته

این ماکروها در ساخت‌ نخ‌آزاد همچنان برای جلوگیری از بن‌بست‌ها ضروری هستند.

Py_BEGIN_ALLOW_THREADS
This macro is available when compiling for the ABI پایدار.

این ماکرو به { PyThreadState *_save; _save = PyEval_SaveThread(); بسط می‌یابد. توجه داشته باشید که این ماکرو یک آکولاد باز در بر دارد و باید با ماکروی Py_END_ALLOW_THREADS که پس از آن می‌آید جفت شود. برای بحث بیشتر درباره‌ی این ماکرو به بالا مراجعه کنید.

Py_END_ALLOW_THREADS
This macro is available when compiling for the ABI پایدار.

این ماکرو به PyEval_RestoreThread(_save); } بسط می‌یابد. توجه داشته باشید که این ماکرو شامل یک آکولاد بسته است و باید با یک ماکروی Py_BEGIN_ALLOW_THREADS پیشین جفت شود. برای بحث بیشتر درباره‌ی این ماکرو، به بالا مراجعه کنید.

Py_BLOCK_THREADS
This macro is available when compiling for the ABI پایدار.

این ماکرو به PyEval_RestoreThread(_save); بسط می‌یابد: معادل Py_END_ALLOW_THREADS بدون آکولاد پایانی است.

Py_UNBLOCK_THREADS
This macro is available when compiling for the ABI پایدار.

این ماکرو به _save = PyEval_SaveThread(); بسط می‌یابد: معادل Py_BEGIN_ALLOW_THREADS بدون آکولاد باز و اعلان متغیر است.

استفاده از API زبان C از نخ‌های خارجی

وقتی نخ‌ها با استفاده از APIهای اختصاصی پایتون (مانند ماژول threading) ایجاد می‌شوند، یک وضعیت نخ به‌طور خودکار با آن‌ها مرتبط می‌شود؛ با این حال، وقتی یک نخ از کد بومی ایجاد شود (برای مثال، توسط یک کتابخانه شخص ثالث با مدیریت نخ اختصاصی خودش)، وضعیت نخ متصل‌شده‌ای ندارد.

اگر لازم باشد کد پایتون را از این نخ‌ها فراخوانی کنید (اغلب این کار بخشی از یک API کال‌بک ارائه‌شده توسط کتابخانه شخص ثالث مذکور خواهد بود)، باید ابتدا با ایجاد یک وضعیت نخ جدید و پیوست دادن آن، این نخ‌ها را در مفسر ثبت کنید.

ساده‌ترین راه برای انجام این کار استفاده از PyThreadState_Ensure() یا PyThreadState_EnsureFromView() است.

نکته

این تابع‌ها به آرگومانی نیاز دارند که به مفسر مورد نظر اشاره کند؛ چنین اشاره‌گری را می‌توان از طریق فراخوانی PyInterpreterGuard_FromCurrent() (برای PyThreadState_Ensure) یا PyInterpreterView_FromCurrent() (برای PyThreadState_EnsureFromView) از تابعی که نخ را ایجاد می‌کند، به‌دست آورد. اگر هیچ اشاره‌گری در دسترس نباشد (مانند زمانی که کتابخانه‌ی نخ بومیِ داده‌شده آرگومان داده‌ای فراهم نمی‌کند)، می‌توانید از PyInterpreterView_FromMain() برای دریافت یک نما برای مفسر اصلی استفاده کنید، اما توجه داشته باشید که این کار کد را با زیرمفسرها ناسازگار می‌کند.

برای مثال:

// The return value of PyInterpreterGuard_FromCurrent() from the
// function that created this thread.
PyInterpreterGuard *guard = thread_data->guard;

// Create a new thread state for the interpreter.
PyThreadStateToken *token = PyThreadState_Ensure(guard);
if (token == NULL) {
   PyInterpreterGuard_Close(guard);
   return;
}

// We have a valid thread state -- perform Python actions here.
result = CallSomeFunction();
// Evaluate result or handle exceptions.

// Release the thread state. No calls to the C API are allowed beyond this
// point.
PyThreadState_Release(token);
PyInterpreterGuard_Close(guard);

به خاطر داشته باشید که فراخوانی PyThreadState_Ensure ممکن است همیشه یک وضعیت نخ جدید ایجاد نکند و فراخوانی PyThreadState_Release ممکن است همیشه آن را جدا نکند. این تابع‌ها ممکن است یک وضعیت نخ متصلِ موجود را دوباره استفاده کنند، یا وضعیت نخی را که قبلاً برای نخ فعلی متصل شده بود، دوباره متصل کنند.

همچنین ببینید

PEP 788

استفاده‌ی مجدد از وضعیت نخ در فراخوانی‌های مکرر

ایجاد و نابود کردن یک PyThreadState رایگان نیست و در یک ساخت نخ‌آزاد هزینه‌ی بیشتری دارد. یک نخ خارجی که بارها مفسر را فراخوانی می‌کند -- برای مثال، یک نخ کارگر در یک استخر نخ بومی -- باید از ایجاد وضعیت نخ جدید در هر بار ورود و نابود کردن آن در هر بار خروج خودداری کند. در عوض، هنگامی که نخ شروع به کار می‌کند (یا به صورت تنبل در اولین فراخوانی‌اش به پایتون)، یک وضعیت نخ را راه‌اندازی کنید، آن را در اطراف هر فراخوانی متصل و جدا کنید، و هنگامی که نخ خارج می‌شود، آن را یک بار از بین ببرید.

وضعیت نخ را به صراحت با PyThreadState_New() مدیریت کنید و آن را با PyEval_RestoreThread() و PyEval_SaveThread() متصل و جدا کنید. این کار در سه مرحله‌ی مجزا، در نقاط مختلفی از چرخه‌ی حیات نخ رخ می‌دهد.

هنگامی که نخ شروع به کار می‌کند، یک وضعیت نخ برای آن ایجاد کنید. interp مفسر هدف است که توسط کدی که این نخ را ایجاد کرده است، در حالی که یک وضعیت نخ متصل را نگه می‌داشت (برای مثال از طریق PyInterpreterState_Get())، گرفته شده است:

PyThreadState *tstate = PyThreadState_New(interp);

سپس، در هر فراخوانی به پایتون -- که ممکن است بارها در طول چرخه‌ی حیات نخ رخ دهد -- وضعیت نخ را متصل کنید، فراخوانی‌های API زبان C پایتون را که به آن نیاز دارند انجام دهید، و دوباره آن را جدا کنید تا نخ در حالی که کارهای غیرپایتونی انجام می‌دهد، GIL را نگه ندارد:

PyEval_RestoreThread(tstate);
result = CallSomeFunction();  /* فراخوانی‌های API زبان C پایتون شما در اینجا قرار می‌گیرند */
PyEval_SaveThread();

هنگامی که کار نخ با فراخوانی پایتون به پایان رسید، وضعیت نخ را یک بار نابود کنید:

PyEval_RestoreThread(tstate);
PyThreadState_Clear(tstate);
PyThreadState_DeleteCurrent();

نقاط ورودی همه‌منظوره برای فراخوانی از یک نخ خارجی -- یعنی PyThreadState_Ensure() و PyGILState_Ensure() قدیمی -- پایداری وضعیت نخ را تضمین نمی‌کنند: طول عمر وضعیت نخِ آن‌ها عمدتاً توسط پیاده‌سازی تعریف می‌شود، بنابراین ممکن است یک جفت به‌دست‌آوردن/آزاد کردنِ منطبق، در هر بار یک وضعیت نخ ایجاد و نابود کند. هر زمان که به‌طور خاص می‌خواهید از یک وضعیت نخ در میان فراخوانی‌ها استفاده مجدد کنید، همان‌طور که در اینجا نشان داده شده است، از PyThreadState_New() استفاده کنید.

کدی که نخ خارجی را ایجاد کرده است باید ترتیبی دهد که دنباله‌ی خاموشی قبل از خروج نخ و قبل از فراخوانی Py_FinalizeEx() اجرا شود. اگر نهایی‌سازی مفسر ابتدا آغاز شود، فراخوانی خاموشی PyEval_RestoreThread() به جای بازگشت، نخ را معلق می‌کند (نگاه کنید به احتیاط‌های مربوط به نهایی‌سازی مفسر). اگر نخ بدون اجرای دنباله‌ی خاموشی خارج شود، وضعیت نخ برای بقیه روند پردازش نشت می‌کند.

اتصال و جداسازی وضعیت‌های نخ

PyThreadStateToken *PyThreadState_Ensure(PyInterpreterGuard *guard)
قسمتی از ABI پایدار از نسخه‌ی 3.15.

اطمینان حاصل کنید که نخ دارای یک وضعیت نخ متصل برای مفسری است که توسط guard محافظت می‌شود، و بنابراین می‌تواند با خیال راحت آن مفسر را فراخوانی کند.

اگر نخ از قبل دارای یک وضعیت نخ متصل باشد، فراخوانی این تابع اشکالی ندارد، به شرطی که فراخوانی بعدی برای PyThreadState_Release() وجود داشته باشد که با این یکی مطابقت داشته باشد (به این معنا که فراخوانی‌های «تودرتو» به این تابع مجاز هستند).

تأثیر تابع (در صورت وجود) توسط فراخوانی منطبق به PyThreadState_Release() معکوس خواهد شد.

هنگام خطا، این تابع NULL را بدون تنظیم هیچ استثنایی برمی‌گرداند. در این صورت PyThreadState_Release() را فراخوانی نکنید.

در صورت موفقیت، این تابع یک مقدار اشاره‌گر بازمی‌گرداند که باید به فراخوانی متناظر در PyThreadState_Release() پاس داده شود.

شرایطی که در آن‌ها این تابع یک وضعیت نخ جدید ایجاد می‌کند، ناپایدار و وابسته به پیاده‌سازی در نظر گرفته می‌شوند. اگر نیاز دارید طول عمر دقیق یک وضعیت نخ را کنترل کنید، استفاده از PyThreadState_New() را در نظر بگیرید. با این حال، صرفاً به این دلیل که ممکن است طول عمر وضعیت نخ در نسخه‌های مختلف ناسازگار باشد، از این تابع اجتناب نکنید؛ تغییرات در این تابع با احتیاط و به شیوه‌ای سازگار با گذشته انجام خواهد شد. به‌ویژه، ذخیره‌سازی متغیرهای نخ‌محلی (thread-local) و وضعیت‌های مشابه در نسخه‌های مختلف پایتون حفظ خواهد شد.

رفتار دقیق این که آیا این تابع یک وضعیت نخ جدید ایجاد می‌کند یا خیر، در ادامه شرح داده شده است، اما آگاه باشید که ممکن است در آینده تغییر کند.

ابتدا، این تابع بررسی می‌کند که آیا یک وضعیت نخ متصل حضور دارد یا خیر. اگر چنین باشد، این تابع سپس بررسی می‌کند که آیا مفسر آن وضعیت نخ با مفسر محافظت‌شده توسط guard مطابقت دارد یا خیر. اگر چنین باشد، این تابع صرفاً وضعیت نخ را به عنوان در حال استفاده توسط یک فراخوانی PyThreadState_Ensure علامت‌گذاری می‌کند و برمی‌گردد.

اگر هیچ وضعیت نخ متصلی وجود نداشته باشد، این تابع بررسی می‌کند که آیا هیچ وضعیت نخی توسط نخ جاری سیستم‌عامل استفاده شده است یا خیر. (این مقدار توسط PyGILState_GetThisThreadState() بازگردانده می‌شود.) اگر وجود داشته باشد، این تابع بررسی می‌کند که آیا مفسر آن وضعیت نخ با guard مطابقت دارد یا خیر. اگر مطابقت داشته باشد، مجدداً متصل شده و به عنوان استفاده‌شده علامت‌گذاری می‌شود.

در غیر این صورت، اگر هر دو مورد بالا با شکست مواجه شوند، یک وضعیت نخ جدید برای guard ایجاد می‌شود. سپس متصل شده و به عنوان متعلق به PyThreadState_Ensure علامت‌گذاری می‌شود.

اضافه شده در نسخه‌ی 3.15.

PyThreadStateToken *PyThreadState_EnsureFromView(PyInterpreterView *view)
قسمتی از ABI پایدار از نسخه‌ی 3.15.

یک وضعیت نخ متصل برای مفسر ارجاع‌داده‌شده توسط view را دریافت کنید.

رفتار و مقدار بازگشتی مشابه PyThreadState_Ensure() است؛ علاوه بر این، اگر تابع موفق باشد، مفسر ارجاع‌داده‌شده توسط view به‌طور ضمنی محافظت خواهد شد. این محافظ پس از فراخوانی متناظر PyThreadState_Release() آزاد خواهد شد.

اضافه شده در نسخه‌ی 3.15.

void PyThreadState_Release(PyThreadStateToken *token)
قسمتی از ABI پایدار از نسخه‌ی 3.15.

یک فراخوانی PyThreadState_Ensure() یا PyThreadState_EnsureFromView() را خنثی کنید.

این تابع باید دقیقاً یک بار برای هر فراخوانی موفق Ensure، در حالی که token روی مقدار بازگشتی آن فراخوانی تنظیم شده است، فراخوانی شود.

وضعیتی که پیش از فراخوانی متناظر Ensure (در صورت وجود) متصل شده بود، هنگام بازگشت PyThreadState_Release() متصل خواهد شد.

رفتار دقیق این که آیا این تابع یک وضعیت نخ را حذف می‌کند یا خیر، ناپایدار و وابسته به پیاده‌سازی در نظر گرفته می‌شود.

در حال حاضر، این تابع یک شمارنده‌ی داخلی را در وضعیت نخ متصل کاهش می‌دهد. اگر این شمارنده روزی به زیر صفر برسد، این تابع یک خطای مهلک (از طریق Py_FatalError()) صادر می‌کند.

اگر وضعیت نخ متصل متعلق به PyThreadState_Ensure باشد، با رسیدن شمارنده‌ی داخلی به صفر، وضعیت نخ متصل از تخصیص خارج و حذف خواهد شد. در غیر این صورت، با رسیدن شمارنده به صفر اتفاقی نمی‌افتد.

اضافه شده در نسخه‌ی 3.15.

type PyThreadStateToken
قسمتی از ABI پایدار (به‌عنوان یک ساختار مبهم) از نسخه‌ی 3.15.

یک توکن کدر که از یک فراخوانی PyThreadState_Ensure() بازیابی شده و به یک فراخوانی متناظر PyThreadState_Release() پاس داده می‌شود.

APIهای وضعیت قفل مفسر سراسری

رابط‌های برنامه‌نویسی کاربردی (API) زیر به‌طور کلی با زیرمفسرها سازگار نیستند و فرایند را در طول نهایی‌سازی مفسر متوقف (Hang) خواهند کرد (به احتیاط‌های مربوط به نهایی‌سازی مفسر مراجعه کنید). به همین دلیل، این APIها در پایتون ۳.۱۵ به نفع رابط‌های جدید به‌طور نرم‌افزاری منسوخ شدند.

type PyGILState_STATE
قسمتی از ABI پایدار.

نوع مقداری که توسط PyGILState_Ensure() بازگردانده می‌شود و به PyGILState_Release() پاس داده می‌شود.

enumerator PyGILState_LOCKED

هنگام فراخوانی PyGILState_Ensure()، قفل مفسر سراسری از قبل گرفته شده بود.

enumerator PyGILState_UNLOCKED

قفل مفسر سراسری هنگام فراخوانی PyGILState_Ensure() در اختیار گرفته نشده بود.

PyGILState_STATE PyGILState_Ensure()
قسمتی از ABI پایدار.

تضمین می‌کند که نخ فعلی، صرف‌نظر از وضعیت فعلی پایتون یا وضعیت نخ متصل، برای فراخوانی Python C API آماده باشد. یک نخ می‌تواند این تابع را به هر تعداد که مطلوب است فراخوانی کند، به شرط آن‌که هر فراخوانی با یک فراخوانی PyGILState_Release() جفت شود. به‌طور کلی، می‌توان بین فراخوانی‌های PyGILState_Ensure() و PyGILState_Release() از سایر APIهای مربوط به نخ استفاده کرد، به شرط آن‌که وضعیت نخ پیش از Release() به وضعیت پیشین خود بازگردانی شود. برای نمونه، استفاده‌ی معمول از ماکروهای Py_BEGIN_ALLOW_THREADS و Py_END_ALLOW_THREADS قابل‌قبول است.

مقدار بازگشتی، یک «دسته» مات برای attached thread state در زمان فراخوانی PyGILState_Ensure() است و باید به PyGILState_Release() پاس داده شود تا اطمینان حاصل شود که پایتون در همان وضعیت باقی می‌ماند. هرچند فراخوانی‌های بازگشتی مجاز هستند، این دسته‌ها نمی‌توانند به اشتراک گذاشته شوند؛ هر فراخوانی مجزای PyGILState_Ensure() باید دسته را برای فراخوانی خود به PyGILState_Release() ذخیره کند.

هنگامی که تابع برمی‌گردد، یک وضعیت نخ متصل وجود خواهد داشت و نخ قادر خواهد بود کد دلخواه پایتون را فراخوانی کند.

این تابع هیچ راهی برای بازگرداندن خطا ندارد. به همین دلیل، خطاها یا مهلک هستند (یعنی SIGABRT را ارسال کرده و فرایند را دچار فروپاشی می‌کنند؛ به Py_FatalError() مراجعه کنید)، یا نخ به‌طور دائم مسدود خواهد شد (مانند طول نهایی‌سازی مفسر).

هشدار

فراخوانی این تابع هنگامی که مفسر در حال نهایی‌سازی است، نخ را به طور بی‌نهایت معلق خواهد کرد که ممکن است باعث ایجاد بن‌بست شود. برای جزئیات بیشتر به احتیاط‌های مربوط به نهایی‌سازی مفسر مراجعه کنید.

علاوه بر این، این تابع هنگامی که از نخ‌های خارجی استفاده می‌شود، معمولاً با زیرمفسرها کار نمی‌کند، زیرا این تابع راهی برای دانستن اینکه کدام مفسر نخ را ایجاد کرده است ندارد (و به همین دلیل، به‌طور ضمنی مفسر اصلی را انتخاب خواهد کرد).

تغییر یافته در نسخه‌ی 3.14: اگر در حین نهایی‌سازی مفسر فراخوانی شود، نخ فعلی را معلق می‌کند، نه اینکه آن را خاتمه دهد.

منسوخ‌سازی نرم <Soft deprecated> از نسخه‌ی 3.15: به‌جای آن از PyThreadState_Ensure() یا PyThreadState_EnsureFromView() استفاده کنید.

void PyGILState_Release(PyGILState_STATE)
قسمتی از ABI پایدار.

هر منبعی که قبلاً کسب شده است را آزاد کنید. پس از این فراخوانی، وضعیت پایتون همانند وضعیت قبل از فراخوانی متناظر PyGILState_Ensure() خواهد بود (اما به طور کلی این وضعیت برای فراخواننده ناشناخته خواهد بود، از این رو استفاده از API وضعیت GIL توصیه می‌شود).

هر فراخوانی PyGILState_Ensure() باید با یک فراخوانی PyGILState_Release() روی همان نخ متناظر باشد.

منسوخ‌سازی نرم <Soft deprecated> از نسخه‌ی 3.15: به جای آن از PyThreadState_Release() استفاده کنید.

PyThreadState *PyGILState_GetThisThreadState()
قسمتی از ABI پایدار.

دریافت وضعیت نخ که اخیراً برای این نخ متصل شده است. (اگر جدیدترین وضعیت نخ حذف شده باشد، این تابع NULL را برمی‌گرداند.)

اگر فراخواننده دارای وضعیت نخ متصلی باشد، آن وضعیت برگردانده می‌شود.

به عبارت دیگر، این تابع وضعیت نخی را برمی‌گرداند که توسط PyGILState_Ensure() استفاده خواهد شد. اگر این تابع NULL را برگرداند، آنگاه PyGILState_Ensure یک وضعیت نخ جدید ایجاد خواهد کرد.

این تابع نمی‌تواند با شکست مواجه شود.

منسوخ‌سازی نرم <Soft deprecated> از نسخه‌ی 3.15: به‌جای آن از PyThreadState_Get() یا PyThreadState_GetUnchecked() استفاده کنید.

int PyGILState_Check()

اگر نخ فعلی دارای یک وضعیت نخ متصل باشد که با وضعیت نخ بازگردانده‌شده توسط PyGILState_GetThisThreadState() مطابقت دارد، مقدار 1 را بازگردانید. اگر فراخواننده هیچ وضعیت نخ متصلی نداشته باشد یا به شکلی دیگر مطابقت نکند، این تابع 0 را برمی‌گرداند.

اگر فرایند کنونی پایتون تا به حال یک زیرمفسر ایجاد کرده باشد، این تابع همیشه مقدار 1 را برمی‌گرداند.

این تابع عمدتاً یک تابع کمکی/عیب‌یابی است.

اضافه شده در نسخه‌ی 3.4.

منسوخ‌سازی نرم <Soft deprecated> از نسخه‌ی 3.15: به‌جای آن از PyThreadState_GetUnchecked() != NULL استفاده کنید.

هشدارهایی درباره‌ی fork()

نکته‌ی مهم دیگری که درباره‌ی نخ‌ها باید به آن توجه کرد، رفتار آن‌ها در برابر فراخوانی C fork() است. در بیشتر سیستم‌هایی که fork() را دارند، پس از انشعاب یک فرایند، تنها نخی که انشعاب را انجام داده است، وجود خواهد داشت. این موضوع هم بر نحوه‌ی مدیریت قفل‌ها و هم بر تمام وضعیت ذخیره‌شده در ران‌تایم سی‌پایتون تأثیر ملموسی دارد.

این واقعیت که فقط نخ «فعلی» باقی می‌ماند، به این معناست که هر قفلی که توسط نخ‌های دیگر نگه‌داشته شده است، هرگز آزاد نخواهد شد. پایتون این مشکل را برای os.fork() با گرفتن قفل‌های داخلی خود پیش از انشعاب و آزاد کردن آن‌ها پس از آن حل می‌کند. علاوه بر این، پایتون هر اشیای قفل را در فرزند بازنشانی می‌کند. هنگام توسعه یا تعبیه پایتون، هیچ راهی برای اطلاع دادن به پایتون درباره‌ی قفل‌های اضافی (غیرپایتونی) که باید پیش از انشعاب گرفته شوند یا پس از آن بازنشانی شوند، وجود ندارد. برای انجام همین کار، لازم است از امکانات سیستم‌عامل مانند pthread_atfork() استفاده شود. افزون بر این، هنگام توسعه یا تعبیه پایتون، فراخوانی مستقیم fork() به‌جای فراخوانی آن از طریق os.fork() (و بازگشت به پایتون یا فراخوانی کدهای پایتون) ممکن است به بن‌بست منجر شود؛ زیرا یکی از قفل‌های داخلی پایتون توسط نخی نگه‌داشته می‌شود که پس از انشعاب از کار افتاده است. PyOS_AfterFork_Child() می‌کوشد قفل‌های لازم را بازنشانی کند، اما همیشه قادر به انجام آن نیست.

این واقعیت که همه نخ‌های دیگر از بین می‌روند، همچنین به این معناست که وضعیت ران‌تایم سی‌پایتون در آن‌جا باید به‌درستی پاک‌سازی شود، که os.fork() این کار را انجام می‌دهد. این به معنای نهایی کردن همه اشیاء دیگر PyThreadState متعلق به مفسر فعلی و همه اشیاء دیگر PyInterpreterState است. به دلیل این موضوع و ماهیت خاص مفسر «اصلی»، fork() باید فقط در نخ «اصلی» آن مفسر فراخوانی شود، جایی که ران‌تایم سراسری سی‌پایتون در ابتدا راه‌اندازی شده بود. تنها استثنا زمانی است که exec() بلافاصله پس از آن فراخوانی شود.

APIهای سطح‌بالا

این‌ها پرکاربردترین نوع‌ها و توابع هنگام نوشتن توسعه‌های C چندنخی هستند.

type PyThreadState
قسمتی از ABI پایدار (به‌عنوان یک ساختار مبهم).

این ساختار داده، وضعیت یک نخ منفرد را نشان می‌دهد. تنها عضو داده‌ی عمومی عبارت است از:

PyInterpreterState *interp

وضعیت مفسر این نخ.

void PyEval_InitThreads()
قسمتی از ABI پایدار.

تابع منسوخ که هیچ کاری انجام نمی‌دهد.

در پایتون 3.6 و نسخه‌های قدیمی‌تر، این تابع در صورت عدم وجود، قفل مفسر سراسری را ایجاد می‌کرد.

تغییر یافته در نسخه‌ی 3.9: تابع اکنون هیچ کاری انجام نمی‌دهد.

تغییر یافته در نسخه‌ی 3.7: این تابع اکنون توسط Py_Initialize() فراخوانی می‌شود، بنابراین دیگر لازم نیست خودتان آن را فراخوانی کنید.

تغییر یافته در نسخه‌ی 3.2: این تابع دیگر نمی‌تواند پیش از Py_Initialize() فراخوانی شود.

منسوخ شده از نسخه‌ی 3.9.

PyThreadState *PyEval_SaveThread()
قسمتی از ABI پایدار.

attached thread state را جدا کنید و آن را برگردانید. پس از بازگشت، نخ هیچ thread state نخواهد داشت.

void PyEval_RestoreThread(PyThreadState *tstate)
قسمتی از ABI پایدار.

وضعیت نخ متصل را به tstate تنظیم کنید. وضعیت نخ ارسال‌شده نباید متصل باشد، در غیر این صورت بن‌بست رخ می‌دهد. پس از بازگشت، tstate متصل خواهد شد.

نکته

فراخوانی این تابع از یک نخ در زمانی که ران‌تایم در حال نهایی‌سازی است، باعث می‌شود نخ تا زمان خروج از برنامه معلق بماند، حتی اگر آن نخ توسط پایتون ایجاد نشده باشد. برای جزئیات بیشتر به احتیاط‌های مربوط به نهایی‌سازی مفسر مراجعه کنید.

تغییر یافته در نسخه‌ی 3.14: اگر در حین نهایی‌سازی مفسر فراخوانی شود، نخ فعلی را معلق می‌کند، نه اینکه آن را خاتمه دهد.

PyThreadState *PyThreadState_Get()
قسمتی از ABI پایدار.

attached thread state را برمی‌گرداند. اگر نخ وضعیت نخ متصلی نداشته باشد (مانند زمانی که درون بلوک Py_BEGIN_ALLOW_THREADS هستیم)، خطای مهلک ایجاد می‌شود (تا فراخواننده نیازی به بررسی NULL نداشته باشد).

همچنین PyThreadState_GetUnchecked() را ببینید.

PyThreadState *PyThreadState_GetUnchecked()

مشابه PyThreadState_Get()، اما اگر NULL باشد، فرایند را با خطای مهلک از بین نمی‌برد. فراخواننده مسئول بررسی NULL بودن نتیجه است.

اضافه شده در نسخه‌ی 3.13: در پایتون 3.5 تا 3.12، این تابع خصوصی بود و به نام _PyThreadState_UncheckedGet() شناخته می‌شد.

PyThreadState *PyThreadState_Swap(PyThreadState *tstate)
قسمتی از ABI پایدار.

attached thread state را روی tstate تنظیم می‌کند و thread state را که پیش از فراخوانی متصل بوده است، بازمی‌گرداند.

فراخوانی این تابع بدون وضعیت نخ متصل ایمن است؛ این تابع صرفاً NULL را برمی‌گرداند که نشان می‌دهد هیچ وضعیت نخ پیشینی وجود نداشته است.

همچنین ببینید

PyEval_ReleaseThread()

نکته

مشابه PyGILState_Ensure()، این تابع در صورتی که ران‌تایم در حال نهایی‌سازی باشد، نخ را معلق می‌کند.

APIهای سطح پایین

PyThreadState *PyThreadState_New(PyInterpreterState *interp)
قسمتی از ABI پایدار.

یک شیء وضعیت نخ جدید متعلق به شیء مفسر داده‌شده ایجاد کنید. به یک وضعیت نخ متصل نیازی نیست.

void PyThreadState_Clear(PyThreadState *tstate)
قسمتی از ABI پایدار.

تمام اطلاعات در یک شیء وضعیت نخ را بازنشانی می‌کند. tstate باید متصل باشد

تغییر یافته در نسخه‌ی 3.9: این تابع اکنون کال‌بک PyThreadState.on_delete را فراخوانی می‌کند. پیش‌تر، این کار در PyThreadState_Delete() انجام می‌شد.

تغییر یافته در نسخه‌ی 3.13: کال‌بک PyThreadState.on_delete حذف شد.

void PyThreadState_Delete(PyThreadState *tstate)
قسمتی از ABI پایدار.

یک شیء وضعیت نخ را نابود می‌کند. tstate نباید به هیچ نخی متصل باشد. tstate باید پیش‌تر با فراخوانی PyThreadState_Clear() بازنشانی شده باشد.

void PyThreadState_DeleteCurrent(void)

وضعیت نخ متصل را جدا کنید (که باید پیش‌تر با یک فراخوانی از PyThreadState_Clear() بازنشانی شده باشد) و سپس آن را نابود کنید.

پس از بازگشت، هیچ thread stateای پیوست نخواهد شد.

PyFrameObject *PyThreadState_GetFrame(PyThreadState *tstate)
قسمتی از ABI پایدار از نسخه‌ی 3.10.

گرفتن فریم فعلی وضعیت نخ پایتون tstate.

یک ارجاع قوی را برمی‌گرداند. اگر هیچ فریمی هم‌اکنون در حال اجرا نباشد، NULL را برمی‌گرداند.

همچنین ببینید PyEval_GetFrame().

tstate نباید NULL باشد، و باید متصل باشد.

اضافه شده در نسخه‌ی 3.9.

uint64_t PyThreadState_GetID(PyThreadState *tstate)
قسمتی از ABI پایدار از نسخه‌ی 3.10.

شناسه‌ی یکتای thread state را از وضعیت نخ پایتون tstate دریافت کنید.

tstate نباید NULL باشد، و باید متصل باشد.

اضافه شده در نسخه‌ی 3.9.

PyInterpreterState *PyThreadState_GetInterpreter(PyThreadState *tstate)
قسمتی از ABI پایدار از نسخه‌ی 3.10.

مفسر وضعیت نخ پایتون tstate را برمی‌گرداند.

tstate نباید NULL باشد، و باید متصل باشد.

اضافه شده در نسخه‌ی 3.9.

void PyThreadState_EnterTracing(PyThreadState *tstate)

ردگیری و پروفایل‌گیری را در وضعیت نخ پایتون tstate تعلیق می‌کند.

برای از سر گرفتن آن‌ها، از تابع PyThreadState_LeaveTracing() استفاده کنید.

اضافه شده در نسخه‌ی 3.11.

void PyThreadState_LeaveTracing(PyThreadState *tstate)

ردگیری و پروفایل‌گیری را در وضعیت نخ پایتون tstate که توسط تابع PyThreadState_EnterTracing() معلق شده است، از سر می‌گیرد.

همچنین توابع PyEval_SetTrace() و PyEval_SetProfile() را ببینید.

اضافه شده در نسخه‌ی 3.11.

int PyUnstable_ThreadState_SetStackProtection(PyThreadState *tstate, void *stack_start_addr, size_t stack_size)
این است API ناپایداراین ممکن است بدون هشدار در نسخه‌های جزئی تغییر کند.

آدرس شروع حفاظت پشته و اندازه حفاظت پشته‌ی یک وضعیت نخ پایتون را تنظیم می‌کند.

در صورت موفقیت، 0 برمی‌گرداند. در صورت شکست، یک استثنا تنظیم کرده و -1 برمی‌گرداند.

سی‌پایتون کنترل بازگشت را برای کد C به این صورت پیاده‌سازی می‌کند که وقتی متوجه می‌شود که پشته اجرای ماشین نزدیک به سرریز است، RecursionError ایجاد می‌کند. برای نمونه، تابع Py_EnterRecursiveCall() را ببینید. برای این کار، سی‌پایتون باید مکان پشته نخ فعلی را بداند که معمولاً آن را از سیستم‌عامل دریافت می‌کند. هنگامی که پشته تغییر می‌کند، مثلاً با استفاده از تکنیک‌های تعویض زمینه مانند boost::context در کتابخانه Boost، باید PyUnstable_ThreadState_SetStackProtection() را فراخوانی کنید تا سی‌پایتون را از این تغییر مطلع کنید.

تابع PyUnstable_ThreadState_SetStackProtection() را یا پیش از تغییر پشته یا پس از آن فراخوانی کنید. بین این فراخوانی و تغییر پشته، هیچ فراخوانی دیگری به C API پایتون انجام ندهید.

برای بازگردانی این عملیات، به PyUnstable_ThreadState_ResetStackProtection() مراجعه کنید.

اضافه شده در نسخه‌ی 3.15.

void PyUnstable_ThreadState_ResetStackProtection(PyThreadState *tstate)
این است API ناپایداراین ممکن است بدون هشدار در نسخه‌های جزئی تغییر کند.

نشانی شروع حفاظت پشته و اندازه حفاظت پشته وضعیت نخ پایتون را به پیش‌فرض‌های سیستم‌عامل بازنشانی می‌کند.

برای توضیح به PyUnstable_ThreadState_SetStackProtection() مراجعه کنید.

اضافه شده در نسخه‌ی 3.15.

PyObject *PyThreadState_GetDict()
مقدار بازگشتی: مرجع امانتی. قسمتی از ABI پایدار.

یک دیکشنری برمی‌گرداند که افزونه‌ها می‌توانند اطلاعات وضعیت مخصوص نخ را در آن ذخیره کنند. هر افزونه باید برای ذخیره‌سازی وضعیت در دیکشنری، از یک کلید یکتا استفاده کند. اشکالی ندارد این تابع را زمانی که هیچ thread state متصل نیست، فراخوانی کنید. اگر این تابع NULL برگرداند، هیچ استثنایی مطرح نشده است و فراخوان‌کننده باید فرض کند که هیچ وضعیت نخی متصل نیست.

void PyEval_AcquireThread(PyThreadState *tstate)
قسمتی از ABI پایدار.

tstate را، که نباید NULL یا از قبل پیوست‌شده باشد، به نخ فعلی پیوست می‌کند.

نخ فراخواننده نباید از قبل یک attached thread state داشته باشد.

نکته

فراخوانی این تابع از یک نخ در زمانی که ران‌تایم در حال نهایی‌سازی است، باعث می‌شود نخ تا زمان خروج از برنامه معلق بماند، حتی اگر آن نخ توسط پایتون ایجاد نشده باشد. برای جزئیات بیشتر به احتیاط‌های مربوط به نهایی‌سازی مفسر مراجعه کنید.

تغییر یافته در نسخه‌ی 3.8: به‌روزرسانی شد تا با PyEval_RestoreThread()، Py_END_ALLOW_THREADS() و PyGILState_Ensure() سازگار باشد و اگر در حین نهایی‌سازی مفسر فراخوانی شود، نخ جاری را خاتمه می‌دهد.

تغییر یافته در نسخه‌ی 3.14: اگر در حین نهایی‌سازی مفسر فراخوانی شود، نخ فعلی را معلق می‌کند، نه اینکه آن را خاتمه دهد.

PyEval_RestoreThread() تابعی در سطح بالاتر است که همیشه در دسترس است (حتی زمانی که نخ‌ها مقداردهی اولیه نشده باشند).

void PyEval_ReleaseThread(PyThreadState *tstate)
قسمتی از ABI پایدار.

وضعیت نخ متصل را جدا می‌کند. آرگومان tstate، که نباید NULL باشد، تنها برای بررسی این‌که وضعیت نخ متصل را نمایندگی می‌کند استفاده می‌شود --- اگر چنین نباشد، خطای مهلکی گزارش می‌شود.

PyEval_SaveThread() تابعی در سطح بالاتر است که همیشه دسترس‌پذیر است (حتی زمانی که نخ‌ها مقداردهی اولیه نشده باشند).

اطلاع‌رسانی ناهمگام

سازوکاری برای ارسال اعلان‌های ناهمگام به نخ اصلی مفسر ارائه شده است. این اعلان‌ها به شکل یک اشاره‌گر تابع و یک آرگومان اشاره‌گر void هستند.

int Py_AddPendingCall(int (*func)(void*), void *arg)
قسمتی از ABI پایدار.

یک تابع را برای فراخوانی از نخ اصلی مفسر زمان‌بندی می‌کند. در صورت موفقیت، 0 بازگردانده می‌شود و func برای فراخوانی در نخ اصلی در صف قرار می‌گیرد. در صورت شکست، -1 بدون تنظیم هیچ استثنایی بازگردانده می‌شود.

هنگامی که با موفقیت در صف قرار گیرد، func سرانجام از نخ اصلی مفسر با آرگومان arg فراخوانی خواهد شد. این تابع نسبت به کد پایتونی که به‌طور عادی در حال اجراست، به‌صورت ناهمگام فراخوانی خواهد شد، اما با برآورده شدن هر دوی این شرایط:

  • در مرز بایت‌کد؛

  • در حالی که نخ اصلی یک وضعیت نخ متصل را در اختیار دارد (func در نتیجه می‌تواند از تمام API زبان C استفاده کند).

func باید در صورت موفقیت 0 و در صورت شکست همراه با یک استثنای تنظیم‌شده -1 را برگرداند. func برای انجام اطلاع‌رسانی ناهمگام دیگری به‌صورت بازگشتی قطع نمی‌شود، اما اگر وضعیت نخ جداشده باشد، همچنان ممکن است برای تعویض نخ‌ها قطع شود.

این تابع به وضعیت نخ متصل نیاز ندارد. با این حال، برای فراخوانی این تابع در یک زیرمفسر، فراخواننده باید وضعیت نخ متصل داشته باشد. در غیر این صورت، ممکن است تابع func برای فراخوانی از مفسر اشتباه زمان‌بندی شود.

هشدار

این یک تابع سطح پایین است و فقط برای موارد بسیار خاص مفید است. هیچ تضمینی وجود ندارد که func با بیشترین سرعت ممکن فراخوانی شود. اگر نخ اصلی مشغول اجرای یک فراخوانی سیستمی باشد، func قبل از بازگشت فراخوانی سیستمی فراخوانی نخواهد شد. این تابع به‌طور کلی برای فراخوانی کد پایتون از نخ‌های دلخواه C مناسب نیست. در عوض، از PyThreadState_EnsureFromView() استفاده کنید.

اضافه شده در نسخه‌ی 3.1.

تغییر یافته در نسخه‌ی 3.9: اگر این تابع در یک زیرمفسر فراخوانی شود، تابع func اکنون برای فراخوانی از طریق زیرمفسر زمان‌بندی می‌شود، نه از طریق مفسر اصلی. هر زیرمفسر اکنون فهرست فراخوانی‌های زمان‌بندی‌شده‌ی خود را دارد.

تغییر یافته در نسخه‌ی 3.12: این تابع اکنون همیشه func را برای اجرا در مفسر اصلی زمان‌بندی می‌کند.

int Py_MakePendingCalls(void)
قسمتی از ABI پایدار.

همه‌ی فراخوانی‌های در انتظار را اجرا می‌کند. این کار معمولاً به‌طور خودکار توسط مفسر اجرا می‌شود.

این تابع در صورت موفقیت 0 را بازمی‌گرداند و در صورت شکست -1 را به‌همراه یک استثنای تنظیم‌شده بازمی‌گرداند.

اگر این تابع در نخ اصلی مفسر اصلی فراخوانی نشود، این تابع هیچ کاری انجام نمی‌دهد و 0 را برمی‌گرداند. فراخواننده باید یک attached thread state را در اختیار داشته باشد.

اضافه شده در نسخه‌ی 3.1.

تغییر یافته در نسخه‌ی 3.12: این تابع فقط فراخوانی‌های در انتظار را در مفسر اصلی اجرا می‌کند.

int PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
قسمتی از ABI پایدار.

برنامه‌ریزی برای بالا آوردن یک استثنا به شکل ناهمگام در یک نخ. اگر نخ از قبل استثنایی برنامه‌ریزی‌شده داشته باشد، بازنویسی می‌شود.

آرگومان id شناسه‌ی نخِ نخِ هدف است، همان‌طور که توسط PyThread_get_thread_ident() برگردانده می‌شود. exc کلاس استثنایی است که باید بالا برده شود، یا NULL برای پاک کردن استثنای معلق (در صورت وجود).

تعداد وضعیت‌های نخِ تحت تأثیر را برگردانید. اگر id پیدا شود، این مقدار معمولاً 1 است، حتی زمانی که هیچ تغییری ایجاد نشده باشد (مقدار exc داده‌شده از قبل معلق بوده است، یا exc برابر با NULL است اما هیچ استثنایی معلق نیست). اگر شناسه‌ی نخ پیدا نشود، 0 را برگردانید. این تابع هیچ استثنایی را بالا نمی‌برد.

برای جلوگیری از سوءاستفاده‌ی ساده‌لوحانه، باید افزونه‌ی C خود را بنویسید تا این تابع را فراخوانی کند. این تابع باید با یک وضعیت نخ متصل فراخوانی شود. این تابع هیچ ارجاعی را به exc نمی‌رباید لزوماً فراخوانی‌های سیستمی مانند sleep() را متوقف نمی‌کند.

تغییر یافته در نسخه‌ی 3.7: نوع پارامتر id از long به unsigned long تغییر یافت.

APIهای نخ سیستم‌عامل

PYTHREAD_INVALID_THREAD_ID

مقدار نشانگر برای شناسه‌ی نامعتبر نخ.

این در حال حاضر معادل (unsigned long)-1 است.

unsigned long PyThread_start_new_thread(void (*func)(void*), void *arg)
قسمتی از ABI پایدار.

تابع func را با آرگومان arg در یک نخ جدید آغاز می‌کند. نخ حاصل برای پیوستن در نظر گرفته نشده است.

func نباید NULL باشد، اما arg می‌تواند NULL باشد.

در صورت موفقیت، این تابع شناسه‌ی نخ جدید را برمی‌گرداند؛ در صورت شکست، PYTHREAD_INVALID_THREAD_ID را برمی‌گرداند.

فراخواننده نیازی به در اختیار داشتن attached thread state ندارد.

unsigned long PyThread_get_thread_ident(void)
قسمتی از ABI پایدار.

شناسه‌ی نخ فعلی را برمی‌گرداند که هرگز صفر نخواهد بود.

این تابع نمی‌تواند شکست بخورد و فراخوانی‌کننده نیازی به نگه داشتن attached thread state ندارد.

همچنین ببینید

threading.get_ident() و threading.Thread.ident این شناسه را در پایتون در معرض دید قرار می‌دهند.

PyObject *PyThread_GetInfo(void)
قسمتی از ABI پایدار از نسخه‌ی 3.3.

اطلاعات کلی درباره‌ی نخ فعلی را به شکل یک شیء دنباله ساختاری دریافت کنید. این اطلاعات در پایتون به صورت sys.thread_info در دسترس است.

در صورت موفقیت، یک ارجاع قوی جدید به اطلاعات نخ بازگردانده می‌شود؛ در صورت شکست، NULL همراه با یک استثنای تنظیم‌شده بازگردانده می‌شود.

فراخواننده باید یک attached thread state را در اختیار داشته باشد.

PY_HAVE_THREAD_NATIVE_ID

این ماکرو زمانی تعریف می‌شود که سیستم از شناسه‌های نخ بومی پشتیبانی کند.

unsigned long PyThread_get_thread_native_id(void)
قسمتی از ABI پایدار on platforms with native thread IDs.

شناسه بومی نخ فعلی را همان‌طور که توسط هسته سیستم‌عامل به آن اختصاص داده شده است به دست می‌آورد؛ این شناسه هرگز کمتر از صفر نخواهد بود.

این تابع تنها زمانی دسترس‌پذیر است که PY_HAVE_THREAD_NATIVE_ID تعریف‌شده باشد.

این تابع نمی‌تواند شکست بخورد و فراخوانی‌کننده نیازی به نگه داشتن attached thread state ندارد.

همچنین ببینید

threading.get_native_id()

void PyThread_exit_thread(void)
قسمتی از ABI پایدار.

نخ فعلی را خاتمه می‌دهد. این تابع به‌طور کلی ناامن تلقی می‌شود و باید از آن پرهیز کرد. این تابع صرفاً برای سازگاری با نسخه‌های پیشین نگه‌داشته شده است.

فراخوانی این تابع تنها زمانی ایمن است که تمام توابع در کل پشته فراخوانی، به‌گونه‌ای نوشته شده باشند که به‌صورت ایمن اجازه‌ی آن را بدهند.

هشدار

اگر سیستم فعلی از نخ‌های POSIX (که با نام «pthreads» نیز شناخته می‌شوند) استفاده کند، این تابع pthread_exit(3) را فراخوانی می‌کند که تلاش می‌کند واپیمایش پشته (stack unwinding) را انجام دهد و در برخی پیاده‌سازی‌های libc مخرب‌های C++ را فراخوانی کند. اما اگر به یک تابع noexcept برسد، ممکن است فرایند را خاتمه دهد. سایر سیستم‌ها مانند macOS واپیمایش پشته را انجام می‌دهند.

در ویندوز، این تابع _endthreadex() را فراخوانی می‌کند که نخ را بدون فراخوانی مخرب‌های C++ می‌کشد.

در هر صورت، خطر خرابی پشته‌ی نخ وجود دارد.

منسوخ شده از نسخه‌ی 3.14.

void PyThread_init_thread(void)
قسمتی از ABI پایدار.

APIهای PyThread* را مقداردهی اولیه می‌کند. پایتون این تابع را به‌طور خودکار اجرا می‌کند، بنابراین نیاز چندانی به فراخوانی آن از یک ماژول توسعه‌ای وجود ندارد.

int PyThread_set_stacksize(size_t size)
قسمتی از ABI پایدار.

اندازه پشته‌ی نخ فعلی را روی size بایت تنظیم می‌کند.

این تابع در صورت موفقیت 0، در صورت نامعتبر بودن size مقدار -1، یا در صورتی که سیستم از تغییر اندازه پشته پشتیبانی نکند -2 برمی‌گرداند. این تابع استثنایی تنظیم نمی‌کند.

فراخواننده نیازی به در اختیار داشتن attached thread state ندارد.

size_t PyThread_get_stacksize(void)
قسمتی از ABI پایدار.

اندازه پشته نخ فعلی را بر حسب بایت برمی‌گرداند، یا 0 اگر اندازه پشته پیش‌فرض سیستم در حال استفاده باشد.

فراخواننده نیازی به در اختیار داشتن attached thread state ندارد.