2016-04-13 14 views
0

Bu benim uygulamada sorunu yeniden nispeten basit bir programdır: Ben Linux makine çalıştırdığınızdaUygunsuz konu içeriğinde shared_ptr'yi yok etmekten nasıl kaçınabilirsiniz?

#include <boost/asio.hpp> 
#include <boost/asio/steady_timer.hpp> 
#include <boost/noncopyable.hpp> 
#include <boost/thread.hpp> 
#include <chrono> 
#include <functional> 
#include <iostream> 
#include <memory> 

class worker : boost::noncopyable { 
public: 
    explicit worker(boost::asio::io_service& io); 
    ~worker(); 
    void just_do_it(const std::function<void()>& when_done); 

private: 
    boost::asio::io_service& io_; 
    boost::asio::io_service worker_io_; 
    boost::thread thread_; 
}; 

worker::worker(boost::asio::io_service& io) 
: io_(io) 
{ 
    thread_ = boost::thread([this] { 
     boost::asio::io_service::work my_work(worker_io_); 
     worker_io_.run(); 
    }); 
} 

worker::~worker() 
{ 
    worker_io_.stop(); 
    std::clog << "join...\n"; 
    thread_.join(); 
} 

void worker::just_do_it(const std::function<void()>& when_done) 
{ 
    worker_io_.post([this, when_done] { 
     io_.post(when_done); 
     boost::asio::steady_timer(worker_io_, std::chrono::seconds(1)).wait(); 
    }); 
} 

int main() 
{ 
    boost::asio::io_service io; 
    boost::asio::steady_timer timer(io, std::chrono::seconds(5)); 
    timer.async_wait(std::bind([] { std::clog << "terminating...\n"; })); 
    { 
     auto my_worker = std::make_shared<worker>(io); 
     my_worker->just_do_it([my_worker] { 
      std::clog << "did it\n"; 
      my_worker->just_do_it([my_worker] { 
       std::clog << "did it second time\n"; 
       // now my_worker is not needed and we allow it to die 
      }); 
     }); 
    } 
    io.run(); 
} 

görüyorum:

Çünkü shared_ptr ait çöküyor
did it 
did it second time 
join... 
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::thread_resource_error> >' 
    what(): boost thread: trying joining itself: Resource deadlock avoided 
Aborted 

worker` içinde işçi yıkıcı çağırır s iş parçacığı. Bunu şu şekilde düzeltebilirim: Ancak bu bir el ile nesne ömrü yönetimi. Yeni ve silme kullanmaktan çok daha iyi değil. Bunu önlemek için herhangi bir yolu var mı?

+0

Daha sonra iş parçacığına katılmak istiyorsun, değil mi? Yani bunun dışındaki iş parçacığına bir sapa ihtiyacınız var. –

+0

İş parçacığı işçi sınıfı üye değişkenlerini kullanabilir, bu yüzden işçinin imha edilmesinden önce durdurmam gerekir. –

+0

Çözümünüz, sorunlu kodunuzdan daha az otomatik değil, yalnızca işaretçi yok edildiğinde (ve örneğin istisnalarla ilgili olarak 'new'/'delete' el kitabından daha iyi olduğunda) değiştiniz; Başka bir çözümle gelebilirsiniz ama sağladığınız en kolayı IMO gibi görünüyor. – piwi

cevap

1

thread nesnesinin, iş parçacığının kullanım ömrünü yöneten kod tarafından sahip olunması gerekir.

Şu an için thread 'ın ömrü sizin worker sınıfı tarafından yönetilir, ve worker sınıfının yaşam boyu yürütme iş parçacığı tarafından yönetilmektedir.

Bu oldukça temel bir yönetim döngüsüdür.

İşçi yıkımının semantiği de fazlasıyla kafa karıştırıcı. Paylaşılan işaretçiler var ve son paylaşılan işaretçi yok olduğunda, bazı iş parçacığı üzerinde bazı bilinmeyen bir görevi bitiren işlem blokları yok edildi. Bu sistemde hangi referans sayım işlemlerinin engelleneceğini tahmin etmek neredeyse imkansızlaşır.


Bir yaklaşım, işçilerdeki işçiler için zayıf işaretçilerin yakalanmasıdır. Daha sonra, işçi ipliğinin kullanım ömrünü yönetme kodunun hepsi tamamlandığında toplanacak; paylaşılan işaretçi gittiğinde. Genel Konuları bir dış kuruluş tarafından yönetilmesi gerekir.

Kullanışlı olabilecek bir yaklaşım, adlandırılmış görev sıralarına sahip bir iş parçacığı havuzu olur. Her bir görev kuyruğunun sırayla çalışacağı garanti edilir, bu nedenle bir iş parçacığı gibi davranır, ancak kuyruktaki görevlerin aynı iş parçacığında çalışacağını veya bir iş parçacığının beklemede beklemede bir garanti olacağını bir garanti yoktur. sıradaki yeni görevler.

Ad sorguları için bir kılavuz veya bir istekte oluşturulan daha az genel olarak benzersiz bir tanımlayıcı (örneğin, bir tür new 'd işaretçisi gibi) kullanabilirsiniz. İkincisinde, .join() aramanızın karşılığı, iş parçacığı sıranızı atar.

Bu, ham boost iş parçacığı temel öğelerini kullanmadan daha ileriye taşıyor; ama benim tecrübemde std-style primitifleri pthreads stil ipliklerini kullanmanın bir adım ötesindedir, ancak hala istemci kodunda doğrudan kullanmak istediğinizden çok uzaktadırlar.

İlgili konular