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