1b27666c6SShuo Chen// reproduce dead lock if compiled with -DREPRODUCE_BUG 2b27666c6SShuo Chen 3b27666c6SShuo Chen#include "../Mutex.h" 4b27666c6SShuo Chen 5b27666c6SShuo Chen#include <boost/noncopyable.hpp> 6b27666c6SShuo Chen 7b27666c6SShuo Chen#include <memory> 8b27666c6SShuo Chen#include <unordered_map> 9b27666c6SShuo Chen 10b27666c6SShuo Chen#include <assert.h> 11b27666c6SShuo Chen#include <stdio.h> 12b27666c6SShuo Chen#include <unistd.h> 13b27666c6SShuo Chen 14b27666c6SShuo Chenusing std::string; 15b27666c6SShuo Chen 16b27666c6SShuo Chenvoid sleepMs(int ms) 17b27666c6SShuo Chen{ 18b27666c6SShuo Chen usleep(ms * 1000); 19b27666c6SShuo Chen} 20b27666c6SShuo Chen 21b27666c6SShuo Chenclass Stock : boost::noncopyable 22b27666c6SShuo Chen{ 23b27666c6SShuo Chen public: 24b27666c6SShuo Chen Stock(const string& name) 25b27666c6SShuo Chen : name_(name) 26b27666c6SShuo Chen { 27b27666c6SShuo Chen printf("%s: Stock[%p] %s\n", muduo::CurrentThread::name(), this, name_.c_str()); 28b27666c6SShuo Chen } 29b27666c6SShuo Chen 30b27666c6SShuo Chen ~Stock() 31b27666c6SShuo Chen { 32b27666c6SShuo Chen printf("%s: ~Stock[%p] %s\n", muduo::CurrentThread::name(), this, name_.c_str()); 33b27666c6SShuo Chen } 34b27666c6SShuo Chen 35b27666c6SShuo Chen const string& key() const { return name_; } 36b27666c6SShuo Chen 37b27666c6SShuo Chen private: 38b27666c6SShuo Chen string name_; 39b27666c6SShuo Chen}; 40b27666c6SShuo Chen 41b27666c6SShuo Chen 42b27666c6SShuo Chenclass StockFactory : boost::noncopyable 43b27666c6SShuo Chen{ 44b27666c6SShuo Chen public: 45b27666c6SShuo Chen 46b27666c6SShuo Chen std::shared_ptr<Stock> get(const string& key) 47b27666c6SShuo Chen { 48b27666c6SShuo Chen std::shared_ptr<Stock> pStock; 49b27666c6SShuo Chen muduo::MutexLockGuard lock(mutex_); 50b27666c6SShuo Chen std::weak_ptr<Stock>& wkStock = stocks_[key]; 51b27666c6SShuo Chen pStock = wkStock.lock(); 52b27666c6SShuo Chen if (!pStock) 53b27666c6SShuo Chen { 54b27666c6SShuo Chen pStock.reset(new Stock(key), 55b27666c6SShuo Chen [this] (Stock* stock) { deleteStock(stock); }); 56b27666c6SShuo Chen wkStock = pStock; 57b27666c6SShuo Chen } 58b27666c6SShuo Chen return pStock; 59b27666c6SShuo Chen } 60b27666c6SShuo Chen 61b27666c6SShuo Chen private: 62b27666c6SShuo Chen 63b27666c6SShuo Chen void deleteStock(Stock* stock) 64b27666c6SShuo Chen { 65b27666c6SShuo Chen printf("%s: deleteStock[%p]\n", muduo::CurrentThread::name(), stock); 66b27666c6SShuo Chen if (stock) 67b27666c6SShuo Chen { 68b27666c6SShuo Chen sleepMs(500); 69b27666c6SShuo Chen if (mutex_.isLockedByThisThread()) 70b27666c6SShuo Chen { 71b27666c6SShuo Chen printf("WARNING: mutex_ is already locked by this thread, deadlock will happen.\n"); 72b27666c6SShuo Chen } 73b27666c6SShuo Chen muduo::MutexLockGuard lock(mutex_); 74b27666c6SShuo Chen auto it = stocks_.find(stock->key()); 75b27666c6SShuo Chen assert(it != stocks_.end()); 76b27666c6SShuo Chen#ifdef REPRODUCE_BUG 77b27666c6SShuo Chen if (auto x = it->second.lock()) 78b27666c6SShuo Chen { 79b27666c6SShuo Chen assert(stock != x.get()); 80b27666c6SShuo Chen printf("use_count = %ld\n", x.use_count()); 81b27666c6SShuo Chen sleepMs(500); 82b27666c6SShuo Chen printf("use_count = %ld\n", x.use_count()); 83b27666c6SShuo Chen } 84b27666c6SShuo Chen else 85b27666c6SShuo Chen { 86b27666c6SShuo Chen stocks_.erase(it); 87b27666c6SShuo Chen } 88b27666c6SShuo Chen#else 89b27666c6SShuo Chen if (it->second.expired()) 90b27666c6SShuo Chen { 91b27666c6SShuo Chen stocks_.erase(it); 92b27666c6SShuo Chen } 93b27666c6SShuo Chen else 94b27666c6SShuo Chen { 95b27666c6SShuo Chen printf("%s: %s is not expired\n", muduo::CurrentThread::name(), stock->key().c_str()); 96b27666c6SShuo Chen } 97b27666c6SShuo Chen#endif 98b27666c6SShuo Chen } 99b27666c6SShuo Chen delete stock; // sorry, I lied 100b27666c6SShuo Chen } 101b27666c6SShuo Chen 102b27666c6SShuo Chen mutable muduo::MutexLock mutex_; 103b27666c6SShuo Chen std::unordered_map<string, std::weak_ptr<Stock> > stocks_; 104b27666c6SShuo Chen}; 105b27666c6SShuo Chen 106b27666c6SShuo Chenvoid threadB(StockFactory* factory) 107b27666c6SShuo Chen{ 108b27666c6SShuo Chen sleepMs(250); 109b27666c6SShuo Chen auto stock = factory->get("MS"); 110b27666c6SShuo Chen printf("%s: stockB %p\n", muduo::CurrentThread::name(), stock.get()); 111b27666c6SShuo Chen 112b27666c6SShuo Chen sleepMs(500); 113b27666c6SShuo Chen printf("%s: stockB destructs\n", muduo::CurrentThread::name()); 114b27666c6SShuo Chen} 115b27666c6SShuo Chen 116b27666c6SShuo Chenint main() 117b27666c6SShuo Chen{ 118b27666c6SShuo Chen StockFactory factory; 119b27666c6SShuo Chen muduo::Thread thr([&factory] { threadB(&factory); }, "thrB"); 120b27666c6SShuo Chen thr.start(); 121b27666c6SShuo Chen { 122b27666c6SShuo Chen auto stock = factory.get("MS"); 123b27666c6SShuo Chen printf("%s: stock %p\n", muduo::CurrentThread::name(), stock.get()); 124b27666c6SShuo Chen } 125b27666c6SShuo Chen thr.join(); 126b27666c6SShuo Chen} 127