Commit 2093640a authored by Bill Budge's avatar Bill Budge Committed by Commit Bot

[code caching] Fix issues with move semantics in GeneratedCodeCache

- Divides EnqueueAsPendingOperation into two methods, with a new
  TryBeginOperation method to check for any pending operations. This
  allows us to defer creating the PendingOperation until we know we
  need it. Otherwise, move semantics could potentially cause loss of
  data when we discard the PendingOperation. This worked before
  because the callbacks are copyable, and IOBuffer is ref-counted.

- Adds some std::moves for callbacks, and some trivial renaming for
  consistency.

- This is preparation for using mojo_base::BigBuffer for writing too.

Bug: chromium:992991
Change-Id: Ia8b16ba9403da2b95c2c9a57da93a9112fd62b17
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1801757Reviewed-by: default avatarMythri Alle <mythria@chromium.org>
Reviewed-by: default avatarCharlie Reis <creis@chromium.org>
Commit-Queue: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#696977}
parent 44eb4b37
...@@ -147,7 +147,9 @@ class GeneratedCodeCache::PendingOperation { ...@@ -147,7 +147,9 @@ class GeneratedCodeCache::PendingOperation {
const std::string& key() const { return key_; } const std::string& key() const { return key_; }
const scoped_refptr<net::IOBufferWithSize> data() const { return data_; } const scoped_refptr<net::IOBufferWithSize> data() const { return data_; }
ReadDataCallback ReleaseReadCallback() { return std::move(read_callback_); } ReadDataCallback ReleaseReadCallback() { return std::move(read_callback_); }
GetBackendCallback ReleaseCallback() { return std::move(callback_); } GetBackendCallback ReleaseBackendCallback() {
return std::move(backend_callback_);
}
private: private:
PendingOperation(Operation op, PendingOperation(Operation op,
...@@ -160,7 +162,7 @@ class GeneratedCodeCache::PendingOperation { ...@@ -160,7 +162,7 @@ class GeneratedCodeCache::PendingOperation {
const std::string key_; const std::string key_;
const scoped_refptr<net::IOBufferWithSize> data_; const scoped_refptr<net::IOBufferWithSize> data_;
ReadDataCallback read_callback_; ReadDataCallback read_callback_;
GetBackendCallback callback_; GetBackendCallback backend_callback_;
}; };
std::unique_ptr<GeneratedCodeCache::PendingOperation> std::unique_ptr<GeneratedCodeCache::PendingOperation>
...@@ -178,7 +180,7 @@ GeneratedCodeCache::PendingOperation::CreateFetchPendingOp( ...@@ -178,7 +180,7 @@ GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
const ReadDataCallback& read_callback) { const ReadDataCallback& read_callback) {
return base::WrapUnique(new PendingOperation( return base::WrapUnique(new PendingOperation(
Operation::kFetch, std::move(key), scoped_refptr<net::IOBufferWithSize>(), Operation::kFetch, std::move(key), scoped_refptr<net::IOBufferWithSize>(),
read_callback, GetBackendCallback())); std::move(read_callback), GetBackendCallback()));
} }
std::unique_ptr<GeneratedCodeCache::PendingOperation> std::unique_ptr<GeneratedCodeCache::PendingOperation>
...@@ -191,11 +193,11 @@ GeneratedCodeCache::PendingOperation::CreateDeletePendingOp(std::string key) { ...@@ -191,11 +193,11 @@ GeneratedCodeCache::PendingOperation::CreateDeletePendingOp(std::string key) {
std::unique_ptr<GeneratedCodeCache::PendingOperation> std::unique_ptr<GeneratedCodeCache::PendingOperation>
GeneratedCodeCache::PendingOperation::CreateGetBackendPendingOp( GeneratedCodeCache::PendingOperation::CreateGetBackendPendingOp(
GetBackendCallback callback) { GetBackendCallback backend_callback) {
return base::WrapUnique( return base::WrapUnique(
new PendingOperation(Operation::kGetBackend, std::string(), new PendingOperation(Operation::kGetBackend, std::string(),
scoped_refptr<net::IOBufferWithSize>(), scoped_refptr<net::IOBufferWithSize>(),
ReadDataCallback(), std::move(callback))); ReadDataCallback(), std::move(backend_callback)));
} }
GeneratedCodeCache::PendingOperation::PendingOperation( GeneratedCodeCache::PendingOperation::PendingOperation(
...@@ -203,12 +205,12 @@ GeneratedCodeCache::PendingOperation::PendingOperation( ...@@ -203,12 +205,12 @@ GeneratedCodeCache::PendingOperation::PendingOperation(
std::string key, std::string key,
scoped_refptr<net::IOBufferWithSize> buffer, scoped_refptr<net::IOBufferWithSize> buffer,
const ReadDataCallback& read_callback, const ReadDataCallback& read_callback,
GetBackendCallback callback) GetBackendCallback backend_callback)
: op_(op), : op_(op),
key_(std::move(key)), key_(std::move(key)),
data_(buffer), data_(buffer),
read_callback_(read_callback), read_callback_(std::move(read_callback)),
callback_(std::move(callback)) {} backend_callback_(std::move(backend_callback)) {}
GeneratedCodeCache::PendingOperation::~PendingOperation() = default; GeneratedCodeCache::PendingOperation::~PendingOperation() = default;
...@@ -264,9 +266,10 @@ void GeneratedCodeCache::WriteData(const GURL& url, ...@@ -264,9 +266,10 @@ void GeneratedCodeCache::WriteData(const GURL& url,
std::string key = GetCacheKey(url, origin_lock); std::string key = GetCacheKey(url, origin_lock);
// If there is an in progress operation corresponding to this key. Enqueue it // If there is an in progress operation corresponding to this key. Enqueue it
// so we can issue once the in-progress operation finishes. // so we can issue once the in-progress operation finishes.
if (EnqueueAsPendingOperation( if (!TryBeginOperation(key)) {
key, GeneratedCodeCache::PendingOperation::CreateWritePendingOp( EnqueueAsPendingOperation(
key, buffer))) { key, GeneratedCodeCache::PendingOperation::CreateWritePendingOp(
key, buffer));
return; return;
} }
...@@ -295,9 +298,10 @@ void GeneratedCodeCache::FetchEntry(const GURL& url, ...@@ -295,9 +298,10 @@ void GeneratedCodeCache::FetchEntry(const GURL& url,
std::string key = GetCacheKey(url, origin_lock); std::string key = GetCacheKey(url, origin_lock);
// If there is an in progress operation corresponding to this key. Enqueue it // If there is an in progress operation corresponding to this key. Enqueue it
// so we can issue once the in-progress operation finishes. // so we can issue once the in-progress operation finishes.
if (EnqueueAsPendingOperation( if (!TryBeginOperation(key)) {
key, GeneratedCodeCache::PendingOperation::CreateFetchPendingOp( EnqueueAsPendingOperation(
key, read_data_callback))) { key, GeneratedCodeCache::PendingOperation::CreateFetchPendingOp(
key, read_data_callback));
return; return;
} }
...@@ -392,7 +396,7 @@ void GeneratedCodeCache::IssueOperation(PendingOperation* op) { ...@@ -392,7 +396,7 @@ void GeneratedCodeCache::IssueOperation(PendingOperation* op) {
DeleteEntryImpl(op->key()); DeleteEntryImpl(op->key());
break; break;
case kGetBackend: case kGetBackend:
DoPendingGetBackend(op->ReleaseCallback()); DoPendingGetBackend(op->ReleaseBackendCallback());
break; break;
} }
} }
...@@ -593,18 +597,22 @@ void GeneratedCodeCache::IssueQueuedOperationForEntry(const std::string& key) { ...@@ -593,18 +597,22 @@ void GeneratedCodeCache::IssueQueuedOperationForEntry(const std::string& key) {
IssueOperation(op.get()); IssueOperation(op.get());
} }
bool GeneratedCodeCache::EnqueueAsPendingOperation( bool GeneratedCodeCache::TryBeginOperation(const std::string& key) {
const std::string& key,
std::unique_ptr<PendingOperation> op) {
auto it = active_entries_map_.find(key); auto it = active_entries_map_.find(key);
if (it != active_entries_map_.end()) { if (it != active_entries_map_.end())
it->second.emplace(std::move(op)); return false;
return true;
}
// Create a entry to indicate there is a in-progress operation for this key. // Create an entry to indicate there is a in-progress operation for this key.
active_entries_map_[key] = base::queue<std::unique_ptr<PendingOperation>>(); active_entries_map_[key] = base::queue<std::unique_ptr<PendingOperation>>();
return false; return true;
}
void GeneratedCodeCache::EnqueueAsPendingOperation(
const std::string& key,
std::unique_ptr<PendingOperation> op) {
auto it = active_entries_map_.find(key);
DCHECK(it != active_entries_map_.end());
it->second.emplace(std::move(op));
} }
void GeneratedCodeCache::DoPendingGetBackend(GetBackendCallback user_callback) { void GeneratedCodeCache::DoPendingGetBackend(GetBackendCallback user_callback) {
......
...@@ -164,9 +164,12 @@ class CONTENT_EXPORT GeneratedCodeCache { ...@@ -164,9 +164,12 @@ class CONTENT_EXPORT GeneratedCodeCache {
// Issues the queued operation at the front of the queue for the given |key|. // Issues the queued operation at the front of the queue for the given |key|.
void IssueQueuedOperationForEntry(const std::string& key); void IssueQueuedOperationForEntry(const std::string& key);
// Enqueues into the list if there is an in-progress operation. Otherwise // Checks for in-progress operations. If there are none, marks the key as
// creates an entry to indicate there is an active operation. // in-progress and returns true. Otherwise returns false.
bool EnqueueAsPendingOperation(const std::string& key, bool TryBeginOperation(const std::string& key);
// Enqueues the operation as pending for the key. This should only be called
// if TryBeginOperation returned false.
void EnqueueAsPendingOperation(const std::string& key,
std::unique_ptr<PendingOperation> op); std::unique_ptr<PendingOperation> op);
void IssueOperation(PendingOperation* op); void IssueOperation(PendingOperation* op);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment