2012-04-12 25 views
38

Yeni C++ bu std :: thread türüne sahiptir. ÇALIŞIYOR bir cazibe gibi. Artık her bir iş parçacığına daha kolay hata ayıklama için bir ad vermek istiyorum (java'nın yapabildiği gibi).std :: thread - parçanizin isimlendirilmesi

pthread_setname_np(pthread_self(), "thread_name"); 

ama c bunu nasıl ++ 0x: Pthreads ile ben yapardım? Linux sistemlerinde pthreads kullandığını biliyorum ancak uygulamayı taşınabilir hale getirmek istiyorum. Bütün bunlar mümkün mü?

+1

Windows'da, iş parçacığı adı bir hata ayıklayıcı özelliğidir (yani uygulamanın kendisinin dışında izlenir). Sonuç olarak, pthread_getname_np' – MSalters

cevap

26

Bunu yapmanın taşınabilir bir yolu, thread::get_id() numaralı belgeden elde edilen iş parçacığı kimliğinin anahtar sözcüklerini korumaktır. Alternatif olarak, yorumlarda önerildiği gibi, yalnızca ismin içinden isme erişmeniz gerekiyorsa, bir thread_local değişkenini kullanabilirsiniz.

Taşınabilirliğe ihtiyacınız olmasaydı, 'un thread::native_handle() numaralı telefondan elde edilebileceği gibi, beğendiğiniz platforma özgü shenaniganları da yapabilirsiniz. İş parçacığı adlandırma işlevlerindeki _np "posix değil" anlamına geldiğinden, tüm pthreads uygulamalarında kullanılabilir olmayacağından emin olun.

+2

"iş parçacığının kimliği ile girilen adların bir haritası" veya "thread-local storage" eşdeğerine sahip değilsiniz. Yaptığınız hata ayıklama işleminin, sadece adını bilmek istediğiniz iş parçacığının içinden aldığını varsayalım. –

+1

Bu fikri tamamlayacak bir tasarım açısından, uygulamanızda bir threadFactory kullanmayı düşünebilirsiniz. Bu program, hedefleri oluşturulduktan sonra iş parçacığına kaydettirmek ve/veya soyutlamak istediğinizde tüm # ifdef komutlarını kullanmaktır. platforma özel kodu seçmek için ön derleyiciyi kullanın. – Dennis

+7

Adlandırma iş parçacıklarının tüm noktası hata ayıklamayı kolaylaştırmaktır, çünkü hata ayıklayıcı iş parçacığının adını gösterecektir, bu nedenle bazı adlar haritasının dahili olarak tutulması anlamsızdır ... –

9

Alttaki uygulama tanımlı dizgiyi almak için std::thread::native_handle kullanabilirsiniz. Doğal olarak bunun için standart bir işlev yoktur.

Örnek bir here bulabilirsiniz.

3

Pencereler için [debugger], "normal" yöntemi kolayca kullanabilirsiniz; http://msdn.microsoft.com/en-gb/library/xcb2z8hs.aspx

Sadece birçok Linux dağıtımları yanı sıra Windows ile başa çıkmak için bir sarıcı kılmayı

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

Bu muhtemelen işe yarayacak ama genel bir C++ ve dolayısıyla çapraz platform çözümü değil. Bunu önerdiğin için teşekkürler. –

+2

Oh, kesinlikle sadece pencereler, ama hiç kimse size pencerelerde nasıl ayarlanacağını söylememişti. (Ve işe yarıyor, ben kullanıyorum :) –

15

girişimi aracılığıyla elde edebileceği parçacığı kimliği gerekir. Lütfen gereken şekilde düzenleyin.

#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

sadece bunun Windows bölümünün açık olduğundan emin olmak için https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx – BillyT2

+0

Windows'ta da kullanmak isteyebilirsiniz SetThreadDescription() API: http://stackoverflow.com/a/41446477/434413. Bu, yeni MS araçlarında kullanılan yeni resmi API'dir (bu yanıtta gösterilen yöntem, bunu gerçekleştirmenin eski yoludur, yalnızca istisna atıldığında Visual Studio ayıklayıcısının içinde çalışan işlemler için çalışır.). –

+0

Not: RaiseException ile Windows kodu, hata ayıklayıcı ile gerçek zamanlı olarak yakalanır. Yani Eğer bir kez iş parçacığında RaiseException başlatır ve daha sonra hata ayıklayıcı eklerseniz, iş parçacığı adını bilmez. – Sergey

2

ben hem (biz temelde std çok benzer olduğunu kendi Konu sınıfını :: iplik icat olduğu) ve birinde Oldukça yakın zamanda yazdığı ++ 11 c predating bir sistemde yapılır görmüştüm.

Temel olarak, havuz gerçekten std :: thread 2 katmanlarını koyar - std :: thread ve adı, kimliği gibi meta veriler içeren bir PoolThread sınıfına sahip olursunuz. havuzu kontrol etmek ve ThreadPool kendisi. Çeşitli nedenlerle çoğu iş parçacıklı koddaki iş parçacığı havuzlarını kullanmak istersiniz:
1) Kullanıcılardan std :: thread konstrüksiyonu, vb. Gibi tüm "detach", "join", iş parçacığı dizisini başlatabilirsiniz. Bu MUCH daha güvenli & temizleyici kodu üretir.
2) Daha iyi kaynak yönetimi: Çok fazla iş parçacığı, performansı çok az olandan bile daha fazla sakat bırakacaktır. İyi inşa edilmiş bir havuz, otomatik yük dengeleme ve temizleme asımı veya kilitlenmemiş dişler gibi gelişmiş şeyler yapabilir.
3) Thread reuse: std :: thread kendi başına her bir paralel görevi kendi iş parçacığı üzerinde çalıştırarak kullanmak en kolay olanıdır. Ancak iplik oluşturma & tahribatı pahalıdır ve dikkatli değilseniz, paralel işlemeden kolayca hız artışı yapabilirsiniz. Bu nedenle, genellikle bir işten bir iş kuyruğu çeken ve yalnızca bazı sinyalleri aldıktan sonra çıkacak havuz iş parçacıklarına sahip olmak daha mantıklıdır.
4) Hata işleme: std :: iş parçacığı yalnızca bir yürütme içeriğidir. Üzerinde çalıştığınız görev işlenmemiş bir istisna atarsa ​​veya std :: thread ITSELF başarısız olursa, işlem hemen burada kilitlenir.Hataya toleranslı çoklu iş parçacığı yapmak için, bu tür şeyleri hızlıca yakalayabilen ve en azından işlem bitmeden önce anlamlı hata iletileri yayabilecek bir Havuza veya benzer bir şeye ihtiyacınız vardır.

+4

Bulunduğunuz yer 2: Programınızı, asma veya kilitlenmemiş konuları temizlemek için mantık eklerseniz, yalnızca hataları gizlemeye çalışıyorsunuz. Bunun yerine hatayı düzeltmenizi tavsiye ederim. Benzer bir şey nokta 4 için de geçerli: İş parçacığının en üst düzeyine işlenmemiş bir özel durum alırsanız, kodunuzda önemli bir hata vardır. Yine, önceliği düzeltmek ve durumu "incelikle" ele almamak olmalıdır. – cmaster

İlgili konular