रीएंट्रेंट फ़ंक्शन की परिभाषा
एक फ़ंक्शन को रीएंट्रेंट फ़ंक्शन कहा जाता है यदि उस फ़ंक्शन को एक्जीक्यूशन के दौरान इंटरप्ट करने का प्रावधान है, फिर ISR (इंटरप्ट सर्विस रूटीन) को सर्विस करें, और फिर टास्क को रिज्यूम करें। इस प्रकार के फ़ंक्शन्स का उपयोग विभिन्न मामलों में किया जाता है जैसे रिकर्सन, हार्डवेयर इंटरप्ट हैंडलिंग।
रीएंट्रेंट फ़ंक्शन के गुण
- कोई ग्लोबल या स्टेटिक वेरिएबल्स नहीं: कोई प्रतिबंध नहीं, लेकिन आमतौर पर सलाह नहीं दी जाती। क्योंकि इंटरप्ट ग्लोबल वेरिएबल के मान बदल सकता है, इसलिए ISR से वापस आने पर फ़ंक्शन को कुछ नया मान मिल सकता है, और परिणाम अलग होंगे
- अपना कोड संशोधित नहीं करता: फ़ंक्शन की क्रिया पूरे कोड में समान रहनी चाहिए
- कोई नॉन-रीएंट्रेंट फ़ंक्शन कॉल नहीं करता: एक रीएंट्रेंट फ़ंक्शन को किसी अन्य नॉन-रीएंट्रेंट फ़ंक्शन को कॉल नहीं करना चाहिए
उदाहरण: नॉन-रीएंट्रेंट फ़ंक्शन्स
int x; // ग्लोबल वेरिएबल
int my_function() {
return x * 10; // ग्लोबल वेरिएबल उपयोग करता है - नॉन-रीएंट्रेंट
}
int my_second_function() {
return my_function() * 20; // नॉन-रीएंट्रेंट फ़ंक्शन कॉल करता है - नॉन-रीएंट्रेंट
}
उदाहरण: रीएंट्रेंट फ़ंक्शन्स
int my_function(int x) { // पैरामीटर द्वारा डेटा प्राप्त करता है
return x * 10;
}
int my_second_function(int x) {
return my_function(x) * 20; // केवल रीएंट्रेंट फ़ंक्शन कॉल करता है
}
अब ये दोनों फ़ंक्शन्स रीएंट्रेंट फ़ंक्शन्स हैं।
रीएंट्रेंसी vs थ्रेड सेफ्टी
| पहलू | रीएंट्रेंसी | थ्रेड सेफ्टी |
|---|---|---|
| चिंता | कंट्रोल फ्लो इंटरप्शन (ISR, सिग्नल, रिकर्सन) | समवर्ती एक्सेस (मल्टीपल थ्रेड्स) |
| मुख्य आवश्यकता | शेयर्ड स्टेट नहीं (या सावधानीपूर्वक प्रबंधित) | सिंक्रोनाइज़ेशन (म्यूटेक्स, एटॉमिक्स) |
| रिकर्सन | अलग चिंता | |
| सिग्नल हैंडलर्स | केवल एसिंक-सिग्नल-सेफ फ़ंक्शन्स कॉल कर सकते हैं | लागू नहीं |
एसिंक-सिग्नल-सेफ फ़ंक्शन्स (POSIX)
सिग्नल हैंडलर्स में केवल इन फ़ंक्शन्स को कॉल किया जा सकता है (आंशिक सूची):
_exit, write, read, closesigaction, sigprocmask, sigemptysetfork, execपरिवार- नहीं: malloc, free, printf, pthread_*, अधिकांश लाइब्रेरी फ़ंक्शन्स
रीएंट्रेंट फ़ंक्शन लिखने के दिशानिर्देश
- सभी डेटा को पैरामीटर्स के रूप में पास करें (ग्लोबल/स्टेटिक से बचें)
- मैलोक/फ्री से बचें (या थ्रेड-सेफ एलोकेटर का उपयोग करें)
- केवल रीएंट्रेंट लाइब्रेरी फ़ंक्शन्स कॉल करें
- थ्रेड-लोकल स्टोरेज (
thread_local) का उपयोग करें यदि प्रति-थ्रेड स्टेट आवश्यक हो - पैरामीटर्स के लिए
constसहीता का उपयोग करें
रीएंट्रेंट स्ट्रिंग फ़ंक्शन उदाहरण (POSIX)
// नॉन-रीएंट्रेंट: स्टेटिक बफर उपयोग करता है
char* strtok(char* str, const char* delim);
// रीएंट्रेंट वर्जन: उपयोगकर्ता-प्रदत्त बफर
char* strtok_r(char* str, const char* delim, char** saveptr);
// उपयोग:
char str[] = "a,b,c";
char* saveptr;
char* token = strtok_r(str, ",", &saveptr);
while (token) {
printf("%s\n", token);
token = strtok_r(NULL, ",", &saveptr);
}