Chromium Code Reviews| Index: content/browser/gpu/shader_disk_cache_impl.cc |
| diff --git a/content/browser/gpu/shader_disk_cache.cc b/content/browser/gpu/shader_disk_cache_impl.cc |
| similarity index 60% |
| rename from content/browser/gpu/shader_disk_cache.cc |
| rename to content/browser/gpu/shader_disk_cache_impl.cc |
| index ca309370e259798aa72dcbda0b89baf470e0037a..e64a223eb175b7a6afab21ea32cc65966816f7a8 100644 |
| --- a/content/browser/gpu/shader_disk_cache.cc |
| +++ b/content/browser/gpu/shader_disk_cache_impl.cc |
| @@ -2,7 +2,7 @@ |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| -#include "content/browser/gpu/shader_disk_cache.h" |
| +#include "content/browser/gpu/shader_disk_cache_impl.h" |
| #include "base/threading/thread_checker.h" |
| #include "content/browser/gpu/gpu_process_host.h" |
| @@ -101,6 +101,40 @@ class ShaderDiskReadHelper |
| DISALLOW_COPY_AND_ASSIGN(ShaderDiskReadHelper); |
| }; |
| +class ShaderClearHelper |
| + : public base::ThreadChecker, |
|
jonathan.backer
2013/03/21 21:06:36
nix: ThreadChecker is for CalledOnValidThread, whi
dsinclair
2013/03/22 18:08:23
Done.
|
| + public base::RefCounted<ShaderClearHelper> { |
| + public: |
| + ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache, |
| + const base::FilePath& path, |
| + const base::Time& delete_begin, |
| + const base::Time& delete_end, |
| + const base::Closure& callback); |
| + void Clear(); |
| + |
| + private: |
| + friend class base::RefCounted<ShaderClearHelper>; |
| + |
| + enum OpType { |
| + TERMINATE, |
| + VERIFY_CACHE_SETUP, |
| + DELETE_CACHE |
| + }; |
| + |
| + ~ShaderClearHelper(); |
| + |
| + void DoClearShaderCache(int rv); |
| + |
| + scoped_refptr<ShaderDiskCache> cache_; |
| + OpType op_type_; |
| + base::FilePath path_; |
| + base::Time delete_begin_; |
| + base::Time delete_end_; |
| + base::Closure callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ShaderClearHelper); |
| +}; |
| + |
| ShaderDiskCacheEntry::ShaderDiskCacheEntry(base::WeakPtr<ShaderDiskCache> cache, |
| const std::string& key, |
| const std::string& shader) |
| @@ -309,51 +343,162 @@ ShaderDiskReadHelper::~ShaderDiskReadHelper() { |
| base::Bind(&EntryCloser, entry_)); |
| } |
| +ShaderClearHelper::ShaderClearHelper(scoped_refptr<ShaderDiskCache> cache, |
| + const base::FilePath& path, |
| + const base::Time& delete_begin, |
| + const base::Time& delete_end, |
| + const base::Closure& callback) |
| + : cache_(cache), |
| + op_type_(VERIFY_CACHE_SETUP), |
| + path_(path), |
| + delete_begin_(delete_begin), |
| + delete_end_(delete_end), |
| + callback_(callback) { |
| +} |
| + |
| +ShaderClearHelper::~ShaderClearHelper() { |
|
jonathan.backer
2013/03/21 21:06:36
Does it matter what thread the |cache| is deleted
dsinclair
2013/03/22 18:08:23
Done.
|
| +} |
| + |
| +void ShaderClearHelper::Clear() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DoClearShaderCache(net::OK); |
| +} |
| + |
| +void ShaderClearHelper::DoClearShaderCache(int rv) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + while (rv != net::ERR_IO_PENDING) { |
| + switch (op_type_) { |
| + case VERIFY_CACHE_SETUP: |
| + rv = cache_->SetAvailableCallback( |
| + base::Bind(&ShaderClearHelper::DoClearShaderCache, this)); |
| + op_type_ = DELETE_CACHE; |
| + break; |
| + case DELETE_CACHE: |
| + rv = cache_->Clear( |
| + delete_begin_, delete_end_, |
| + base::Bind(&ShaderClearHelper::DoClearShaderCache, this)); |
| + op_type_ = TERMINATE; |
| + break; |
| + case TERMINATE: |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + base::Bind(&ShaderCacheFactoryImpl::CacheCleared, |
| + base::Unretained(ShaderCacheFactoryImpl::GetInstance()), |
| + path_)); |
|
jonathan.backer
2013/03/21 21:06:36
nit: Comment for the PostTask. This won't be clear
dsinclair
2013/03/22 18:08:23
Done.
|
| + callback_.Run(); |
| + rv = net::ERR_IO_PENDING; // Break the loop. |
| + break; |
| + default: |
| + NOTREACHED(); // Invalid state provided. |
| + op_type_ = TERMINATE; |
| + break; |
| + } |
| + } |
| +} |
| + |
| +// static |
| ShaderCacheFactory* ShaderCacheFactory::GetInstance() { |
| - return Singleton<ShaderCacheFactory, |
| - LeakySingletonTraits<ShaderCacheFactory> >::get(); |
| + return ShaderCacheFactoryImpl::GetInstance(); |
| +} |
| + |
| +// static |
| +ShaderCacheFactoryImpl* ShaderCacheFactoryImpl::GetInstance() { |
| + return Singleton<ShaderCacheFactoryImpl, |
| + LeakySingletonTraits<ShaderCacheFactoryImpl> >::get(); |
| } |
| -ShaderCacheFactory::ShaderCacheFactory() { |
| +ShaderCacheFactoryImpl::ShaderCacheFactoryImpl() { |
| } |
| -ShaderCacheFactory::~ShaderCacheFactory() { |
| +ShaderCacheFactoryImpl::~ShaderCacheFactoryImpl() { |
| } |
| -void ShaderCacheFactory::SetCacheInfo(int32 client_id, |
| - const base::FilePath& path) { |
| - client_id_to_path_map_[client_id] = path.Append(kGpuCachePath); |
| +void ShaderCacheFactoryImpl::SetCacheInfo(int32 client_id, |
| + const base::FilePath& path) { |
| + client_id_to_path_map_[client_id] = path; |
| } |
| -void ShaderCacheFactory::RemoveCacheInfo(int32 client_id) { |
| +void ShaderCacheFactoryImpl::RemoveCacheInfo(int32 client_id) { |
| client_id_to_path_map_.erase(client_id); |
| } |
| -scoped_refptr<ShaderDiskCache> ShaderCacheFactory::Get(int32 client_id) { |
| - ClientIdToPathMap::iterator client_iter = |
| +scoped_refptr<ShaderDiskCache> ShaderCacheFactoryImpl::Get( |
| + int32 client_id) { |
| + ClientIdToPathMap::iterator iter = |
| client_id_to_path_map_.find(client_id); |
| - if (client_iter == client_id_to_path_map_.end()) |
| + if (iter == client_id_to_path_map_.end()) |
| return NULL; |
| + return ShaderCacheFactoryImpl::GetByPath(iter->second); |
| +} |
| - ShaderCacheMap::iterator iter = shader_cache_map_.find(client_iter->second); |
| +scoped_refptr<ShaderDiskCache> ShaderCacheFactoryImpl::GetByPath( |
| + const base::FilePath& path) { |
| + ShaderCacheMap::iterator iter = shader_cache_map_.find(path); |
| if (iter != shader_cache_map_.end()) |
| return iter->second; |
| - ShaderDiskCache* cache = new ShaderDiskCache(client_iter->second); |
| + ShaderDiskCache* cache = new ShaderDiskCache(path); |
| cache->Init(); |
| - |
| return cache; |
| } |
| -void ShaderCacheFactory::AddToCache(const base::FilePath& key, |
| - ShaderDiskCache* cache) { |
| +void ShaderCacheFactoryImpl::AddToCache(const base::FilePath& key, |
| + ShaderDiskCache* cache) { |
| shader_cache_map_[key] = cache; |
| } |
| -void ShaderCacheFactory::RemoveFromCache(const base::FilePath& key) { |
| +void ShaderCacheFactoryImpl::RemoveFromCache(const base::FilePath& key) { |
| shader_cache_map_.erase(key); |
| } |
| +void ShaderCacheFactoryImpl::ClearByPath(const base::FilePath& path, |
| + const base::Time& delete_begin, |
| + const base::Time& delete_end, |
| + const base::Closure& callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + DCHECK(!callback.is_null()); |
| + |
| + scoped_refptr<ShaderClearHelper> helper = new ShaderClearHelper( |
| + GetByPath(path), path, delete_begin, delete_end, callback); |
| + |
| + // We could receive requests to clear the same path with different |
| + // begin/end times. So, we keep a list of requests. If we haven't seen this |
| + // path before we kick off the clear and add it to the list. If we have see it |
| + // already, then we already have a clear running. We add this clear to the |
| + // list and wait for any previous clears to finish. |
| + ShaderClearMap::iterator iter = shader_clear_map_.find(path); |
| + if (iter != shader_clear_map_.end()) { |
| + iter->second.push(helper); |
| + return; |
| + } |
| + |
| + shader_clear_map_.insert( |
| + std::pair<base::FilePath, ShaderClearQueue>(path, ShaderClearQueue())); |
| + shader_clear_map_[path].push(helper); |
| + helper->Clear(); |
| +} |
| + |
| +void ShaderCacheFactoryImpl::CacheCleared(const base::FilePath& path) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + ShaderClearMap::iterator iter = shader_clear_map_.find(path); |
| + if (iter == shader_clear_map_.end()) { |
| + LOG(ERROR) << "Completed clear but missing clear helper."; |
| + return; |
| + } |
| + |
| + iter->second.pop(); |
| + |
| + // If there are remaining items in the list we trigger the Clear on the |
| + // next one. |
| + if (!iter->second.empty()) { |
| + iter->second.front()->Clear(); |
| + return; |
| + } |
| + |
| + shader_clear_map_.erase(path); |
| +} |
| + |
| ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path) |
| : cache_available_(false), |
| max_cache_size_(0), |
| @@ -361,11 +506,11 @@ ShaderDiskCache::ShaderDiskCache(const base::FilePath& cache_path) |
| cache_path_(cache_path), |
| is_initialized_(false), |
| backend_(NULL) { |
| - ShaderCacheFactory::GetInstance()->AddToCache(cache_path_, this); |
| + ShaderCacheFactoryImpl::GetInstance()->AddToCache(cache_path_, this); |
| } |
| ShaderDiskCache::~ShaderDiskCache() { |
| - ShaderCacheFactory::GetInstance()->RemoveFromCache(cache_path_); |
| + ShaderCacheFactoryImpl::GetInstance()->RemoveFromCache(cache_path_); |
| } |
| void ShaderDiskCache::Init() { |
| @@ -377,7 +522,7 @@ void ShaderDiskCache::Init() { |
| int rv = disk_cache::CreateCacheBackend( |
| net::SHADER_CACHE, |
| - cache_path_, |
| + cache_path_.Append(kGpuCachePath), |
| max_cache_size_, |
| true, |
| BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE), |
| @@ -400,16 +545,41 @@ void ShaderDiskCache::Cache(const std::string& key, const std::string& shader) { |
| entry_map_[shim] = shim; |
| } |
| +int ShaderDiskCache::Clear( |
| + const base::Time begin_time, const base::Time end_time, |
| + const net::CompletionCallback& completion_callback) { |
| + int rv; |
| + if (begin_time.is_null()) { |
| + rv = backend_->DoomAllEntries(completion_callback); |
| + } else { |
| + rv = backend_->DoomEntriesBetween(begin_time, end_time, |
| + completion_callback); |
| + } |
| + return rv; |
| +} |
| + |
| +int ShaderDiskCache::SetAvailableCallback( |
| + const net::CompletionCallback& callback) { |
| + if (cache_available_) |
| + return net::OK; |
| + available_callback_ = callback; |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| void ShaderDiskCache::CacheCreatedCallback(int rv) { |
| if (rv != net::OK) { |
| LOG(ERROR) << "Shader Cache Creation failed: " << rv; |
| return; |
| } |
| - |
| cache_available_ = true; |
| helper_ = new ShaderDiskReadHelper(AsWeakPtr(), host_id_); |
| helper_->LoadCache(); |
| + |
| + if (!available_callback_.is_null()) { |
| + available_callback_.Run(net::OK); |
| + available_callback_.Reset(); |
| + } |
| } |
| void ShaderDiskCache::EntryComplete(void* entry) { |