Factory.cc revision 5a94f34b
15a94f34bSShuo Chen#include <map>
25a94f34bSShuo Chen
35a94f34bSShuo Chen#include <boost/bind.hpp>
45a94f34bSShuo Chen#include <boost/enable_shared_from_this.hpp>
55a94f34bSShuo Chen#include <boost/shared_ptr.hpp>
65a94f34bSShuo Chen#include <boost/weak_ptr.hpp>
75a94f34bSShuo Chen
85a94f34bSShuo Chen#include "../Mutex.h"
95a94f34bSShuo Chen
105a94f34bSShuo Chen#include <assert.h>
115a94f34bSShuo Chen#include <stdio.h>
125a94f34bSShuo Chen
135a94f34bSShuo Chenusing std::string;
145a94f34bSShuo Chen
155a94f34bSShuo Chenclass Stock : boost::noncopyable
165a94f34bSShuo Chen{
175a94f34bSShuo Chen public:
185a94f34bSShuo Chen  Stock(const string& name)
195a94f34bSShuo Chen    : name_(name)
205a94f34bSShuo Chen  {
215a94f34bSShuo Chen    printf(" Stock[%p] %s\n", this, name_.c_str());
225a94f34bSShuo Chen  }
235a94f34bSShuo Chen
245a94f34bSShuo Chen  ~Stock()
255a94f34bSShuo Chen  {
265a94f34bSShuo Chen    printf("~Stock[%p] %s\n", this, name_.c_str());
275a94f34bSShuo Chen  }
285a94f34bSShuo Chen
295a94f34bSShuo Chen  const string& key() const { return name_; }
305a94f34bSShuo Chen
315a94f34bSShuo Chen private:
325a94f34bSShuo Chen  string name_;
335a94f34bSShuo Chen};
345a94f34bSShuo Chen
355a94f34bSShuo Chennamespace version1
365a94f34bSShuo Chen{
375a94f34bSShuo Chen
385a94f34bSShuo Chen// questionable code
395a94f34bSShuo Chenclass StockFactory : boost::noncopyable
405a94f34bSShuo Chen{
415a94f34bSShuo Chen public:
425a94f34bSShuo Chen
435a94f34bSShuo Chen  boost::shared_ptr<Stock> get(const string& key)
445a94f34bSShuo Chen  {
455a94f34bSShuo Chen    muduo::MutexLockGuard lock(mutex_);
465a94f34bSShuo Chen    boost::shared_ptr<Stock>& pStock = stocks_[key];
475a94f34bSShuo Chen    if (!pStock)
485a94f34bSShuo Chen    {
495a94f34bSShuo Chen      pStock.reset(new Stock(key));
505a94f34bSShuo Chen    }
515a94f34bSShuo Chen    return pStock;
525a94f34bSShuo Chen  }
535a94f34bSShuo Chen
545a94f34bSShuo Chen
555a94f34bSShuo Chen private:
565a94f34bSShuo Chen  mutable muduo::MutexLock mutex_;
575a94f34bSShuo Chen  std::map<string, boost::shared_ptr<Stock> > stocks_;
585a94f34bSShuo Chen};
595a94f34bSShuo Chen
605a94f34bSShuo Chen}
615a94f34bSShuo Chen
625a94f34bSShuo Chennamespace version2
635a94f34bSShuo Chen{
645a94f34bSShuo Chen
655a94f34bSShuo Chenclass StockFactory : boost::noncopyable
665a94f34bSShuo Chen{
675a94f34bSShuo Chen public:
685a94f34bSShuo Chen  boost::shared_ptr<Stock> get(const string& key)
695a94f34bSShuo Chen  {
705a94f34bSShuo Chen    boost::shared_ptr<Stock> pStock;
715a94f34bSShuo Chen    muduo::MutexLockGuard lock(mutex_);
725a94f34bSShuo Chen    boost::weak_ptr<Stock>& wkStock = stocks_[key];
735a94f34bSShuo Chen    pStock = wkStock.lock();
745a94f34bSShuo Chen    if (!pStock)
755a94f34bSShuo Chen    {
765a94f34bSShuo Chen      pStock.reset(new Stock(key));
775a94f34bSShuo Chen      wkStock = pStock;
785a94f34bSShuo Chen    }
795a94f34bSShuo Chen    return pStock;
805a94f34bSShuo Chen  }
815a94f34bSShuo Chen
825a94f34bSShuo Chen private:
835a94f34bSShuo Chen  mutable muduo::MutexLock mutex_;
845a94f34bSShuo Chen  std::map<string, boost::weak_ptr<Stock> > stocks_;
855a94f34bSShuo Chen};
865a94f34bSShuo Chen
875a94f34bSShuo Chen}
885a94f34bSShuo Chen
895a94f34bSShuo Chennamespace version3
905a94f34bSShuo Chen{
915a94f34bSShuo Chen
925a94f34bSShuo Chenclass StockFactory : boost::noncopyable
935a94f34bSShuo Chen{
945a94f34bSShuo Chen public:
955a94f34bSShuo Chen
965a94f34bSShuo Chen  boost::shared_ptr<Stock> get(const string& key)
975a94f34bSShuo Chen  {
985a94f34bSShuo Chen    boost::shared_ptr<Stock> pStock;
995a94f34bSShuo Chen    muduo::MutexLockGuard lock(mutex_);
1005a94f34bSShuo Chen    boost::weak_ptr<Stock>& wkStock = stocks_[key];
1015a94f34bSShuo Chen    pStock = wkStock.lock();
1025a94f34bSShuo Chen    if (!pStock)
1035a94f34bSShuo Chen    {
1045a94f34bSShuo Chen      pStock.reset(new Stock(key),
1055a94f34bSShuo Chen                   boost::bind(&StockFactory::deleteStock, this, _1));
1065a94f34bSShuo Chen      wkStock = pStock;
1075a94f34bSShuo Chen    }
1085a94f34bSShuo Chen    return pStock;
1095a94f34bSShuo Chen  }
1105a94f34bSShuo Chen
1115a94f34bSShuo Chen private:
1125a94f34bSShuo Chen
1135a94f34bSShuo Chen  void deleteStock(Stock* stock)
1145a94f34bSShuo Chen  {
1155a94f34bSShuo Chen    printf("deleteStock[%p]\n", stock);
1165a94f34bSShuo Chen    if (stock)
1175a94f34bSShuo Chen    {
1185a94f34bSShuo Chen      muduo::MutexLockGuard lock(mutex_);
1195a94f34bSShuo Chen      stocks_.erase(stock->key());
1205a94f34bSShuo Chen    }
1215a94f34bSShuo Chen    delete stock;  // sorry, I lied
1225a94f34bSShuo Chen  }
1235a94f34bSShuo Chen  mutable muduo::MutexLock mutex_;
1245a94f34bSShuo Chen  std::map<string, boost::weak_ptr<Stock> > stocks_;
1255a94f34bSShuo Chen};
1265a94f34bSShuo Chen
1275a94f34bSShuo Chen}
1285a94f34bSShuo Chen
1295a94f34bSShuo Chennamespace version4
1305a94f34bSShuo Chen{
1315a94f34bSShuo Chen
1325a94f34bSShuo Chenclass StockFactory : public boost::enable_shared_from_this<StockFactory>,
1335a94f34bSShuo Chen                     boost::noncopyable
1345a94f34bSShuo Chen{
1355a94f34bSShuo Chen public:
1365a94f34bSShuo Chen
1375a94f34bSShuo Chen  boost::shared_ptr<Stock> get(const string& key)
1385a94f34bSShuo Chen  {
1395a94f34bSShuo Chen    boost::shared_ptr<Stock> pStock;
1405a94f34bSShuo Chen    muduo::MutexLockGuard lock(mutex_);
1415a94f34bSShuo Chen    boost::weak_ptr<Stock>& wkStock = stocks_[key];
1425a94f34bSShuo Chen    pStock = wkStock.lock();
1435a94f34bSShuo Chen    if (!pStock)
1445a94f34bSShuo Chen    {
1455a94f34bSShuo Chen      pStock.reset(new Stock(key),
1465a94f34bSShuo Chen                   boost::bind(&StockFactory::deleteStock,
1475a94f34bSShuo Chen                               shared_from_this(),
1485a94f34bSShuo Chen                               _1));
1495a94f34bSShuo Chen      wkStock = pStock;
1505a94f34bSShuo Chen    }
1515a94f34bSShuo Chen    return pStock;
1525a94f34bSShuo Chen  }
1535a94f34bSShuo Chen
1545a94f34bSShuo Chen private:
1555a94f34bSShuo Chen
1565a94f34bSShuo Chen  void deleteStock(Stock* stock)
1575a94f34bSShuo Chen  {
1585a94f34bSShuo Chen    printf("deleteStock[%p]\n", stock);
1595a94f34bSShuo Chen    if (stock)
1605a94f34bSShuo Chen    {
1615a94f34bSShuo Chen      muduo::MutexLockGuard lock(mutex_);
1625a94f34bSShuo Chen      stocks_.erase(stock->key());
1635a94f34bSShuo Chen    }
1645a94f34bSShuo Chen    delete stock;  // sorry, I lied
1655a94f34bSShuo Chen  }
1665a94f34bSShuo Chen  mutable muduo::MutexLock mutex_;
1675a94f34bSShuo Chen  std::map<string, boost::weak_ptr<Stock> > stocks_;
1685a94f34bSShuo Chen};
1695a94f34bSShuo Chen
1705a94f34bSShuo Chen}
1715a94f34bSShuo Chen
1725a94f34bSShuo Chenclass StockFactory : public boost::enable_shared_from_this<StockFactory>,
1735a94f34bSShuo Chen                     boost::noncopyable
1745a94f34bSShuo Chen{
1755a94f34bSShuo Chen public:
1765a94f34bSShuo Chen  boost::shared_ptr<Stock> get(const string& key)
1775a94f34bSShuo Chen  {
1785a94f34bSShuo Chen    boost::shared_ptr<Stock> pStock;
1795a94f34bSShuo Chen    muduo::MutexLockGuard lock(mutex_);
1805a94f34bSShuo Chen    boost::weak_ptr<Stock>& wkStock = stocks_[key];
1815a94f34bSShuo Chen    pStock = wkStock.lock();
1825a94f34bSShuo Chen    if (!pStock)
1835a94f34bSShuo Chen    {
1845a94f34bSShuo Chen      pStock.reset(new Stock(key),
1855a94f34bSShuo Chen                   boost::bind(&StockFactory::weakDeleteCallback,
1865a94f34bSShuo Chen                               boost::weak_ptr<StockFactory>(shared_from_this()),
1875a94f34bSShuo Chen                               _1));
1885a94f34bSShuo Chen      wkStock = pStock;
1895a94f34bSShuo Chen    }
1905a94f34bSShuo Chen    return pStock;
1915a94f34bSShuo Chen  }
1925a94f34bSShuo Chen
1935a94f34bSShuo Chen private:
1945a94f34bSShuo Chen  static void weakDeleteCallback(boost::weak_ptr<StockFactory> wkFactory,
1955a94f34bSShuo Chen                                 Stock* stock)
1965a94f34bSShuo Chen  {
1975a94f34bSShuo Chen    printf("weakDeleteStock[%p]\n", stock);
1985a94f34bSShuo Chen    boost::shared_ptr<StockFactory> factory(wkFactory.lock());
1995a94f34bSShuo Chen    if (factory)
2005a94f34bSShuo Chen    {
2015a94f34bSShuo Chen      factory->removeStock(stock);
2025a94f34bSShuo Chen    }
2035a94f34bSShuo Chen    else
2045a94f34bSShuo Chen    {
2055a94f34bSShuo Chen      printf("factory died.\n");
2065a94f34bSShuo Chen    }
2075a94f34bSShuo Chen    delete stock;  // sorry, I lied
2085a94f34bSShuo Chen  }
2095a94f34bSShuo Chen
2105a94f34bSShuo Chen  void removeStock(Stock* stock)
2115a94f34bSShuo Chen  {
2125a94f34bSShuo Chen    if (stock)
2135a94f34bSShuo Chen    {
2145a94f34bSShuo Chen      muduo::MutexLockGuard lock(mutex_);
2155a94f34bSShuo Chen      stocks_.erase(stock->key());
2165a94f34bSShuo Chen    }
2175a94f34bSShuo Chen  }
2185a94f34bSShuo Chen
2195a94f34bSShuo Chen private:
2205a94f34bSShuo Chen  mutable muduo::MutexLock mutex_;
2215a94f34bSShuo Chen  std::map<string, boost::weak_ptr<Stock> > stocks_;
2225a94f34bSShuo Chen};
2235a94f34bSShuo Chen
2245a94f34bSShuo Chenvoid testLongLifeFactory()
2255a94f34bSShuo Chen{
2265a94f34bSShuo Chen  boost::shared_ptr<StockFactory> factory(new StockFactory);
2275a94f34bSShuo Chen  {
2285a94f34bSShuo Chen    boost::shared_ptr<Stock> stock = factory->get("NYSE:IBM");
2295a94f34bSShuo Chen    boost::shared_ptr<Stock> stock2 = factory->get("NYSE:IBM");
2305a94f34bSShuo Chen    assert(stock == stock2);
2315a94f34bSShuo Chen    // stock destructs here
2325a94f34bSShuo Chen  }
2335a94f34bSShuo Chen  // factory destructs here
2345a94f34bSShuo Chen}
2355a94f34bSShuo Chen
2365a94f34bSShuo Chenvoid testShortLifeFactory()
2375a94f34bSShuo Chen{
2385a94f34bSShuo Chen  boost::shared_ptr<Stock> stock;
2395a94f34bSShuo Chen  {
2405a94f34bSShuo Chen    boost::shared_ptr<StockFactory> factory(new StockFactory);
2415a94f34bSShuo Chen    stock = factory->get("NYSE:IBM");
2425a94f34bSShuo Chen    boost::shared_ptr<Stock> stock2 = factory->get("NYSE:IBM");
2435a94f34bSShuo Chen    assert(stock == stock2);
2445a94f34bSShuo Chen    // factory destructs here
2455a94f34bSShuo Chen  }
2465a94f34bSShuo Chen  // stock destructs here
2475a94f34bSShuo Chen}
2485a94f34bSShuo Chen
2495a94f34bSShuo Chenint main()
2505a94f34bSShuo Chen{
2515a94f34bSShuo Chen  version1::StockFactory sf1;
2525a94f34bSShuo Chen  version2::StockFactory sf2;
2535a94f34bSShuo Chen  version3::StockFactory sf3;
2545a94f34bSShuo Chen  boost::shared_ptr<version3::StockFactory> sf4(new version3::StockFactory);
2555a94f34bSShuo Chen  boost::shared_ptr<StockFactory> sf5(new StockFactory);
2565a94f34bSShuo Chen
2575a94f34bSShuo Chen  {
2585a94f34bSShuo Chen  boost::shared_ptr<Stock> s1 = sf1.get("stock1");
2595a94f34bSShuo Chen  }
2605a94f34bSShuo Chen
2615a94f34bSShuo Chen  {
2625a94f34bSShuo Chen  boost::shared_ptr<Stock> s2 = sf2.get("stock2");
2635a94f34bSShuo Chen  }
2645a94f34bSShuo Chen
2655a94f34bSShuo Chen  {
2665a94f34bSShuo Chen  boost::shared_ptr<Stock> s3 = sf3.get("stock3");
2675a94f34bSShuo Chen  }
2685a94f34bSShuo Chen
2695a94f34bSShuo Chen  {
2705a94f34bSShuo Chen  boost::shared_ptr<Stock> s4 = sf4->get("stock4");
2715a94f34bSShuo Chen  }
2725a94f34bSShuo Chen
2735a94f34bSShuo Chen  {
2745a94f34bSShuo Chen  boost::shared_ptr<Stock> s5 = sf5->get("stock5");
2755a94f34bSShuo Chen  }
2765a94f34bSShuo Chen
2775a94f34bSShuo Chen  testLongLifeFactory();
2785a94f34bSShuo Chen  testShortLifeFactory();
2795a94f34bSShuo Chen}
280