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..de42c0ec0034fb6d6a4974f73314aaea7bd7fd41 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 unrealistic hence we avoid most of them by |
+ // 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 |