shareable_file_reference.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "storage/common/blob/shareable_file_reference.h" 6 7#include <map> 8 9#include "base/lazy_instance.h" 10#include "base/message_loop/message_loop_proxy.h" 11#include "base/task_runner.h" 12#include "base/threading/non_thread_safe.h" 13 14namespace storage { 15 16namespace { 17 18// A shareable file map with enforcement of thread checker. 19class ShareableFileMap : public base::NonThreadSafe { 20 public: 21 typedef std::map<base::FilePath, ShareableFileReference*> FileMap; 22 typedef FileMap::iterator iterator; 23 typedef FileMap::key_type key_type; 24 typedef FileMap::value_type value_type; 25 26 ShareableFileMap() {} 27 28 ~ShareableFileMap() { 29 DetachFromThread(); 30 } 31 32 iterator Find(key_type key) { 33 DCHECK(CalledOnValidThread()); 34 return file_map_.find(key); 35 } 36 37 iterator End() { 38 DCHECK(CalledOnValidThread()); 39 return file_map_.end(); 40 } 41 42 std::pair<iterator, bool> Insert(value_type value) { 43 DCHECK(CalledOnValidThread()); 44 return file_map_.insert(value); 45 } 46 47 void Erase(key_type key) { 48 DCHECK(CalledOnValidThread()); 49 file_map_.erase(key); 50 } 51 52 private: 53 FileMap file_map_; 54 DISALLOW_COPY_AND_ASSIGN(ShareableFileMap); 55}; 56 57base::LazyInstance<ShareableFileMap> g_file_map = LAZY_INSTANCE_INITIALIZER; 58 59} // namespace 60 61// static 62scoped_refptr<ShareableFileReference> ShareableFileReference::Get( 63 const base::FilePath& path) { 64 ShareableFileMap::iterator found = g_file_map.Get().Find(path); 65 ShareableFileReference* reference = 66 (found == g_file_map.Get().End()) ? NULL : found->second; 67 return scoped_refptr<ShareableFileReference>(reference); 68} 69 70// static 71scoped_refptr<ShareableFileReference> ShareableFileReference::GetOrCreate( 72 const base::FilePath& path, 73 FinalReleasePolicy policy, 74 base::TaskRunner* file_task_runner) { 75 return GetOrCreate( 76 ScopedFile(path, static_cast<ScopedFile::ScopeOutPolicy>(policy), 77 file_task_runner)); 78} 79 80// static 81scoped_refptr<ShareableFileReference> ShareableFileReference::GetOrCreate( 82 ScopedFile scoped_file) { 83 if (scoped_file.path().empty()) 84 return scoped_refptr<ShareableFileReference>(); 85 86 typedef std::pair<ShareableFileMap::iterator, bool> InsertResult; 87 // Required for VS2010: 88 // http://connect.microsoft.com/VisualStudio/feedback/ 89 // details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair 90 storage::ShareableFileReference* null_reference = NULL; 91 InsertResult result = g_file_map.Get().Insert( 92 ShareableFileMap::value_type(scoped_file.path(), null_reference)); 93 if (result.second == false) { 94 scoped_file.Release(); 95 return scoped_refptr<ShareableFileReference>(result.first->second); 96 } 97 98 // Wasn't in the map, create a new reference and store the pointer. 99 scoped_refptr<ShareableFileReference> reference( 100 new ShareableFileReference(scoped_file.Pass())); 101 result.first->second = reference.get(); 102 return reference; 103} 104 105void ShareableFileReference::AddFinalReleaseCallback( 106 const FinalReleaseCallback& callback) { 107 DCHECK(g_file_map.Get().CalledOnValidThread()); 108 scoped_file_.AddScopeOutCallback(callback, NULL); 109} 110 111ShareableFileReference::ShareableFileReference(ScopedFile scoped_file) 112 : scoped_file_(scoped_file.Pass()) { 113 DCHECK(g_file_map.Get().Find(path())->second == NULL); 114} 115 116ShareableFileReference::~ShareableFileReference() { 117 DCHECK(g_file_map.Get().Find(path())->second == this); 118 g_file_map.Get().Erase(path()); 119} 120 121} // namespace storage 122