2012-04-12 23 views
38

नया सी ++ में यह std :: थ्रेड प्रकार है। एक जादू की तरह काम करता है। अब मैं प्रत्येक थ्रेड को अधिक आसान डिबगिंग के लिए एक नाम देना चाहता हूं (जैसे जावा आपको अनुमति देता है)। pthreads के साथ मैं करना होगा:std :: thread - अपने धागे का नामकरण

pthread_setname_np(pthread_self(), "thread_name"); 

लेकिन मैं कैसे ग के साथ ऐसा कर सकते हैं ++ 0x? मुझे पता है कि यह लिनक्स सिस्टम के नीचे pthreads का उपयोग करता है, लेकिन मैं अपना आवेदन पोर्टेबल बनाना चाहता हूं। क्या यह सभी के लिए संभव है?

+1

विंडोज़ पर, थ्रेड नाम एक डीबगर संपत्ति है (यानी एप्लिकेशन के बाहर ट्रैक किया गया है)। नतीजतन, आपके पास 'pthread_getname_np' – MSalters

उत्तर

26

ऐसा करने का एक पोर्टेबल तरीका है thread::get_id() से प्राप्त धागे की आईडी द्वारा की गई नामों का नक्शा बनाए रखना। वैकल्पिक रूप से, टिप्पणियों में सुझाए गए अनुसार, आप thread_local चर का उपयोग कर सकते हैं, अगर आपको केवल थ्रेड के भीतर से नाम तक पहुंचने की आवश्यकता है।

यदि आपको पोर्टेबिलिटी की आवश्यकता नहीं है, तो आप को thread::native_handle() से अंतर्निहित pthread_t प्राप्त कर सकते हैं और जो भी प्लेटफॉर्म-विशिष्ट शेंगेनियां आपको पसंद करते हैं उन्हें करें। ध्यान रखें कि थ्रेड नामकरण कार्यों पर _np का अर्थ है "पॉज़िक्स नहीं", इसलिए वे सभी pthreads कार्यान्वयन पर उपलब्ध होने की गारंटी नहीं है।

+2

" थ्रेड की आईडी द्वारा की गई नामों का मानचित्र "- या थ्रेड-लोकल स्टोरेज के बराबर नहीं है? यह मानते हुए कि आप जो डिबगिंग कर रहे हैं वह केवल थ्रेड के अंदर से है जिसका नाम आप जानना चाहते हैं। –

+1

इस विचार को लपेटने के लिए डिज़ाइन के संदर्भ में, आप अपने आवेदन में थ्रेड फैक्ट्री का उपयोग करने पर विचार करना चाहेंगे, जिसका लक्ष्य सृजन पर धागे को पंजीकृत करना है और/या अमूर्त को '# ifdef' की आवश्यकता है, यदि आप चाहते हैं मंच विशिष्ट कोड का चयन करने के लिए प्री-कंपाइलर का उपयोग करें। – Dennis

+7

नामकरण धागे का पूरा बिंदु डीबगिंग को आसान बनाना है, क्योंकि डीबगर थ्रेड का नाम दिखाएगा, इसलिए कुछ नामों को आंतरिक रूप से मानचित्र बनाए रखना एक प्रकार का व्यर्थ है ... –

9

अंडरलेइंग कार्यान्वयन परिभाषित थ्रेड प्राप्त करने के लिए आप std::thread::native_handle का उपयोग कर सकते हैं। उस मूल रूप से कोई मानक कार्य नहीं है।

आप एक उदाहरण here पा सकते हैं।

3

विंडोज़ [डीबगर] के लिए, आप आसानी से "सामान्य" विधि का उपयोग कर सकते हैं; http://msdn.microsoft.com/en-gb/library/xcb2z8hs.aspx

बस धागा आईडी आप कई Linuxes साथ ही Windows से निपटने के लिए एक आवरण बनाने में के माध्यम से

#include <windows.h> 
DWORD ThreadId = ::GetThreadId(static_cast<HANDLE>(mThread.native_handle())); 
+0

शायद यह काम करेगा लेकिन यह एक सामान्य सी ++ नहीं है और इस प्रकार क्रॉस प्लेटफॉर्म समाधान है। वैसे भी इसे सुझाव देने के लिए धन्यवाद। –

+2

ओह यह निश्चित रूप से केवल विंडोज़ है, लेकिन किसी ने वास्तव में आपको विंडोज़ पर सेट करने के बारे में बताया था। (और यह काम करता है, मैं इसका उपयोग करता हूं :) –

15

का प्रयास प्राप्त कर सकते हैं जो की जरूरत है। कृपया आवश्यकतानुसार संपादित करें।

#ifdef _WIN32 
#include <windows.h> 
const DWORD MS_VC_EXCEPTION=0x406D1388; 

#pragma pack(push,8) 
typedef struct tagTHREADNAME_INFO 
{ 
    DWORD dwType; // Must be 0x1000. 
    LPCSTR szName; // Pointer to name (in user addr space). 
    DWORD dwThreadID; // Thread ID (-1=caller thread). 
    DWORD dwFlags; // Reserved for future use, must be zero. 
} THREADNAME_INFO; 
#pragma pack(pop) 


void SetThreadName(uint32_t dwThreadID, const char* threadName) 
{ 

    // DWORD dwThreadID = ::GetThreadId(static_cast<HANDLE>(t.native_handle())); 

    THREADNAME_INFO info; 
    info.dwType = 0x1000; 
    info.szName = threadName; 
    info.dwThreadID = dwThreadID; 
    info.dwFlags = 0; 

    __try 
    { 
     RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); 
    } 
    __except(EXCEPTION_EXECUTE_HANDLER) 
    { 
    } 
} 
void SetThreadName(const char* threadName) 
{ 
    SetThreadName(GetCurrentThreadId(),threadName); 
} 

void SetThreadName(std::thread* thread, const char* threadName) 
{ 
    DWORD threadId = ::GetThreadId(static_cast<HANDLE>(thread->native_handle())); 
    SetThreadName(threadId,threadName); 
} 

#else 
void SetThreadName(std::thread* thread, const char* threadName) 
{ 
    auto handle = thread->native_handle(); 
    pthread_setname_np(handle,threadName); 
} 


#include <sys/prctl.h> 
void SetThreadName(const char* threadName) 
{ 
    prctl(PR_SET_NAME,threadName,0,0,0); 
} 

#endif 
+1

बस इसके विंडोज़ हिस्से को स्पष्ट करने के लिए https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx – BillyT2

+0

विंडोज पर, आप भी उपयोग करना चाहेंगे SetThreadDescription() API: http://stackoverflow.com/a/41446477/434413। यह नया आधिकारिक एपीआई है, जिसका उपयोग नए एमएस टूल्स में किया जा रहा है (इस उत्तर में दिखाया गया तरीका यह करने का पुराना तरीका है, जो केवल अपवाद फेंकने के समय विजुअल स्टूडियो डीबगर के अंदर चल रही प्रक्रियाओं के लिए काम करता है)। –

+0

नोट: RaiseException के साथ विंडोज कोड डीबगर के साथ वास्तविक समय में पकड़ा जाता है। अर्थात। यदि आप एक बार थ्रेड शुरू करते हैं और बाद में डिबगर संलग्न करते हैं, तो इसे थ्रेड नाम नहीं पता होगा। – Sergey

2

मैं दोनों इस एक प्रणाली C++ 11 (जहां हम मूल रूप से हमारे अपने थ्रेड वर्ग कि std के समान था :: धागा आविष्कार किया) और एक में मैं काफी हाल ही में लिखा था predating में किया देखा है।

मूल रूप से, पूल वास्तव में std :: thread 2 परतों को नीचे रखता है- आपके पास एक पूल थ्रेड क्लास है जिसमें std :: thread plus मेटाडेटा है जिसका नाम, आईडी, इत्यादि और नियंत्रण संरचना जो इसे लिंक करती है पूल को नियंत्रित करना, और थ्रेडपूल स्वयं ही। आप कई थ्रेडेड कोड में थ्रेड पूल का उपयोग कई कारणों से करना चाहते हैं:
1) आप सभी स्पष्ट "अलग करें", "शामिल हों", उपयोगकर्ताओं से std :: thread construction आदि पर थ्रेड प्रारंभ कर सकते हैं। इससे बहुत सुरक्षित & क्लीनर कोड उत्पन्न होता है।
2) बेहतर संसाधन प्रबंधन: बहुत सारे धागे बहुत कम होने से भी अधिक प्रदर्शन को अपंग करेंगे। एक अच्छी तरह से निर्मित पूल उन्नत लोड संतुलन और सफाई-लटका या deadlocked धागे जैसे उन्नत चीजें कर सकते हैं।
3) थ्रेड पुन: उपयोग करें: std :: थ्रेड स्वयं अपने धागे पर प्रत्येक समांतर कार्य को चलाकर उपयोग करना सबसे आसान है। लेकिन धागा निर्माण & विनाश महंगा है, और यदि आप सावधान नहीं हैं तो समानांतर प्रक्रिया से गति वृद्धि को आसानी से घुमा सकते हैं। इसलिए, यह आम तौर पर पूल धागे रखने के लिए अधिक समझ में आता है जो कतार से कार्य कार्यों को खींचता है और कुछ सिग्नल प्राप्त करने के बाद ही बाहर निकलता है।
4) त्रुटि प्रबंधन: std :: thread केवल निष्पादन संदर्भ है। यदि आप जिस कार्य पर चल रहे हैं, वह एक अन-हैंडल अपवाद फेंकता है या std :: thread ITSELF विफल रहता है, तो प्रक्रिया ठीक उसी समय क्रैश हो जाएगी।गलती-सहिष्णु मल्टीथ्रेडिंग करने के लिए, आपको एक पूल या ऐसा कुछ चाहिए जो ऐसी चीजों को जल्दी से पकड़ सके और कम से कम प्रक्रिया से मरने से पहले सार्थक त्रुटि संदेशों को छोड़ दें।

+4

अपने बिंदु 2 के बारे में: यदि आप लटका या deadlocked धागे को साफ करने के लिए अपने प्रोग्राम में तर्क जोड़ते हैं, तो आप केवल बग को छिपाने की कोशिश कर रहे हैं। मैं बदले में बग फिक्स करने की सिफारिश करता हूं। बिंदु 4 के लिए कुछ समान होता है: यदि आपको थ्रेड के शीर्ष स्तर पर एक अनचाहे अपवाद मिलता है, तो आपके कोड में घातक बग है। फिर, प्राथमिकता को बग को ठीक करना चाहिए और स्थिति को संभालने के लिए "कृपापूर्वक" नहीं होना चाहिए। – cmaster

संबंधित मुद्दे