2017-09-12 76 views
6

varsayalım ben uyumsuz bazı kod çalıştırabilir bir sınıf var ve bu uyumsuz kod Açıkçası sınıf örneği bu erişimler için sırayla arka plan iş parçacığı daha uzun yaşamak gerekir, çağrı üye fonksiyonları gibi şeyler yapmak veri üyeleri, vb okumak için sınıf örneğini kullanır güvende olmak. Yıkıcıdaki arka plan iş parçacığına katılarak bunu sağlamak yeterli mi? Örneğin:Yıkıcıya katılarak eşzamansız çalışmayı beklemek güvenli midir?

#include <iostream> 
#include <thread> 

class foo final 
{ 
public: 
    foo() = default; 

    void bar() { 
     std::cout << "Hopefully there's nothing wrong with using " << this << "\n"; 
    } 

    void bar_async() { 
     if (!m_thread.joinable()) { 
      m_thread = std::thread{&foo::bar, this}; 
     } 
    } 

    ~foo() { 
     if (m_thread.joinable()) { 
      std::cout << "Waiting for " << m_thread.get_id() << "\n"; 
      m_thread.join(); 
     } 
    } 

private: 
    std::thread m_thread; 
}; 

int main() { 
    foo f; 
    f.bar_async(); 
} 

Özellikle, object lifetime rules endişeleniyorum: destructor'ın yürütme başladığında

yıkıcı önemsiz değil sınıf türlerinin herhangi bir nesne için

, ömür boyu biter.

... Bir nesnenin ömrü sona erdi ve sonra işgal nesne yeniden kullanılabilir veya serbest depolamadan önce, tanımsız olduğu nesneyi tanımlayan glvalue ifade aşağıdaki kullanım alanları: ...

  • Statik olmayan bir üye üyeye veya statik olmayan üye işlevine yapılan çağrıya erişim.

Ama bana göre yukarıda sıkı bir okuma da ~foo() içinden this->bar() arayarak doğrudan "Açıkçası" hangi durumda değil, tanımsız olduğu anlamına geliyor.

+1

'Final' bir çok problemi çözüyor; Eğer final değilsen son derece dikkatli ol. – Yakk

+0

Bu pratik veya yasal bir soru mu? – curiousguy

+0

@curiousguy Legalistic –

cevap

3

cppreference doğru ama değil yıkıcı ilgili içeriden, nesneden üyelerini erişen bahsediyor. Biz [class.cdtor] en/1 bakarsak yapıcı önce nesnenin bir statik olmayan üye ya da temel sınıf atıfta önemsiz olmayan bir kurucu ile bir nesne için

olup, bu uygulama sonuçları başlar bkz tanımlanmamış davranış. Önemsiz bir yıkıcıya sahip bir nesne için, , yıkıcı tamamlanmadan sonra nesnenin statik olmayan herhangi bir üyesine veya temel sınıfına başvuran tanımsız davranışıyla sonuçlanır.

So sürece biz yıkıcı olarak biz hala yıkıcı biter kapsamı kadar tahrip verilmediğinden dolayı üye nesnelerle çalışabilir vurgu madeni.

Yani, iş parçacığı üzerinde join çağıran burada gayet iyi. Eğer düşünmemiş olsaydın, kilit muhafızlar gibi şeyler, isimlerini verdikleri mutekslere erişemezlerse, faydasız olurdu.

+0

Doğru, özellikle yıkıcıdaki kod hakkında endişe duymuyorum, gerçekten de, beni, beni endişelendiren, yıkıcıyla eşzamanlı olarak yürütülebilen diğer iş parçacığından gelen çubuk() çağrısıdır. –

+0

@TavianBarnes Hangi iplik nedir? Üye iş parçacığı başlatmak için bar_async() işlevini çağırmalısınız. Nesnenin örneğinizde tahrip edilmesiyle aynı anda bu işlevi çağıramazsınız. – NathanOliver

+0

Üye iş parçacığı, 'bar() ' –

0

Sezgim hayırdır. Bunun nedeni, thread :: join öğesinin bir istisna atabilmesi ve destroyerinizden kaçan istisnalar istememenizdir. Eğer bir deneyin yakalama içinde sarın ve yine de istisna olsa düzgün olabilir.

+3

Bu istisnaların nedenlerinin temelde programlama hataları olduğunu unutmayın - kendinize katılmaya çalışın veya birleştirilemeyen bir iş parçacığına katılmaya çalışın. – MSalters

+0

Bir iş parçacığı içinde bir istisna, istisna yakalanan ve atılan iş parçacığında ele alınmazsa, programı hemen sonlandırır. - Bu ipliği birleştiren bir yıkıcı hiç etkilenmez. – CAF