title: How to implement cache manager using std::shared_ptr?
body: <pre><code>#include &lt;mutex&gt;
  #include &lt;assert.h&gt;
  #include &lt;iostream&gt;
  #include &lt;unordered_map&gt;
  #include &lt;memory&gt;
  #include &lt;string&gt;
  #include &lt;stdio.h&gt;
  
  // 
  // Requirements:
  //  1: the bitmap could be used by multiple thread safely.(std::shared_ptr could?)
  //  2: cache the bitmap and do not always increase memeory
  //@NotThreadSfe
  struct Bitmap {
      public:
          Bitmap(const std::string&amp; filePath) { 
              filePath_ = filePath;
              printf("foo %x ctor %s\n", this, filePath_.c_str());
          }
          ~Bitmap() {
              printf("foo %x dtor %s\n", this, filePath_.c_str());
          }
          std::string filePath_;
  };
  
  //@ThreadSafe
  struct BitmapCache {
      public:
          static std::shared_ptr&lt;Bitmap&gt; loadBitmap(const std::string&amp; filePath) {
              mutex_.lock();
  
              //whether in the cache
              auto iter = cache_.find(filePath);
              if (iter != cache_.end()) {
                  if ((*iter).second) {
                      return (*iter).second;
                  } else {
                      std::shared_ptr&lt;Bitmap&gt; newPtr(new Bitmap(filePath));
                      (*iter).second = newPtr;
                      return newPtr;
                  }
              }
  
              //try remove unused elements if possible
              if (cache_.size() &gt;= kSlotThreshold) {
                  std::unordered_map&lt;std::string,std::shared_ptr&lt;Bitmap&gt;&gt;::iterator delIter = cache_.end();
                  for (auto iter = cache_.begin(); iter != cache_.end(); ++iter) {
                      auto&amp; item = *iter;
                      if (item.second &amp;&amp; item.second.use_count() == 1) {
                          delIter = iter;
                          break;
                      }
                  }
                  if (cache_.end() != delIter) {
                      (*delIter).second.reset();
                      cache_.erase(delIter);
                  }
              }
  
              //create new and insert to the cache
              std::shared_ptr&lt;Bitmap&gt; newPtr(new Bitmap(filePath));
              cache_.insert({filePath, newPtr});
              mutex_.unlock();
              return newPtr;
          }
      private:
          static const int kSlotThreshold = 20;
          static std::mutex mutex_;
          static std::unordered_map&lt;std::string,std::shared_ptr&lt;Bitmap&gt;&gt; cache_;
  };
  
  /* static */
  std::unordered_map&lt;std::string,std::shared_ptr&lt;Bitmap&gt;&gt; BitmapCache::cache_;
  
  /* static */
  std::mutex BitmapCache::mutex_;
  
  int main()
  {
      //test for remove useless element
      char buff[200] = {0};
      std::vector&lt;std::shared_ptr&lt;Bitmap&gt;&gt; bmpVec(20);
      for (int i = 0; i &lt; 20; ++i) {
          sprintf_s(buff, 200, "c:\\haha%d.bmp", i);
          bmpVec[i] = BitmapCache::loadBitmap(buff);
      }
      bmpVec[3].reset();
      std::shared_ptr&lt;Bitmap&gt; newBmp = BitmapCache::loadBitmap("c:\\new.bmp");
  
      //test for multiple threading...(to be implemenetd)
      return 0;
  }
  </code></pre>
  
  <p>I am pure new to C++ memory management. Could you please give me a hint: Am I in the right way, or should I employ different design strategy or different memory manager policy(such as weak_ptr etc)?</p>