Chromium Code Reviews| Index: base/files/important_file_writer.cc |
| diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc |
| index 9cbbd736e5baa5b53c2577909ffad724f30e89d4..009bbccf18a66474da7c73e2728b6355233e5233 100644 |
| --- a/base/files/important_file_writer.cc |
| +++ b/base/files/important_file_writer.cc |
| @@ -23,6 +23,7 @@ |
| #include "base/metrics/histogram.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/task_runner.h" |
| +#include "base/task_runner_util.h" |
| #include "base/threading/thread.h" |
| #include "base/time/time.h" |
| @@ -93,13 +94,13 @@ bool ImportantFileWriter::WriteFileAtomically(const FilePath& path, |
| return true; |
| } |
| -ImportantFileWriter::ImportantFileWriter( |
| - const FilePath& path, base::SequencedTaskRunner* task_runner) |
| - : path_(path), |
| - task_runner_(task_runner), |
| - serializer_(NULL), |
| - commit_interval_(TimeDelta::FromMilliseconds( |
| - kDefaultCommitIntervalMs)) { |
| +ImportantFileWriter::ImportantFileWriter(const FilePath& path, |
| + base::SequencedTaskRunner* task_runner) |
| + : path_(path), |
| + task_runner_(task_runner), |
| + serializer_(NULL), |
| + commit_interval_(TimeDelta::FromMilliseconds(kDefaultCommitIntervalMs)), |
| + weak_factory_(this) { |
| DCHECK(CalledOnValidThread()); |
| DCHECK(task_runner_.get()); |
| } |
| @@ -126,11 +127,7 @@ void ImportantFileWriter::WriteNow(const std::string& data) { |
| if (HasPendingWrite()) |
| timer_.Stop(); |
| - if (!task_runner_->PostTask( |
| - FROM_HERE, |
| - MakeCriticalClosure( |
| - Bind(IgnoreResult(&ImportantFileWriter::WriteFileAtomically), |
| - path_, data)))) { |
| + if (!PostWriteTask(data)) { |
| // Posting the task to background message loop is not expected |
| // to fail, but if it does, avoid losing data and just hit the disk |
| // on the current thread. |
| @@ -164,4 +161,40 @@ void ImportantFileWriter::DoScheduledWrite() { |
| serializer_ = NULL; |
| } |
| +void ImportantFileWriter::RegisterOnNextSuccessfulWriteCallback( |
| + const base::Closure& on_next_successful_write) { |
| + DCHECK(on_next_successful_write_.is_null()); |
| + on_next_successful_write_ = on_next_successful_write; |
| +} |
| + |
| +bool ImportantFileWriter::PostWriteTask(const std::string& data) { |
| + // TODO(gab): This code could always use PostTaskAndReplyWithResult and let |
| + // ForwardSuccessfulWrite() no-op if |on_next_successful_write_| is null, but |
| + // PostTaskAndReply causes memory leaks in tests (crbug.com/371974) and |
| + // suppressing all of those is irrealistic hence we avoid most of them by |
|
robertshield
2014/05/12 00:39:13
nit: s/irrealistic/unrealistic/
gab
2014/05/12 02:21:00
Done.
|
| + // using PostTask() in the typical scenario below. |
| + if (!on_next_successful_write_.is_null()) { |
| + return base::PostTaskAndReplyWithResult( |
| + task_runner_, |
| + FROM_HERE, |
| + MakeCriticalClosure( |
| + Bind(&ImportantFileWriter::WriteFileAtomically, path_, data)), |
| + Bind(&ImportantFileWriter::ForwardSuccessfulWrite, |
| + weak_factory_.GetWeakPtr())); |
| + } |
| + return task_runner_->PostTask( |
| + FROM_HERE, |
| + MakeCriticalClosure( |
| + Bind(IgnoreResult(&ImportantFileWriter::WriteFileAtomically), |
| + path_, data))); |
| +} |
| + |
| +void ImportantFileWriter::ForwardSuccessfulWrite(bool result) { |
| + DCHECK(CalledOnValidThread()); |
| + if (result && !on_next_successful_write_.is_null()) { |
| + on_next_successful_write_.Run(); |
| + on_next_successful_write_.Reset(); |
| + } |
| +} |
| + |
| } // namespace base |