1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file.
4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#ifndef TOOLS_ANDROID_FORWARDER2_SELF_DELETER_HELPER_H_
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define TOOLS_ANDROID_FORWARDER2_SELF_DELETER_HELPER_H_
7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/basictypes.h"
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/bind.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/callback.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/location.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/ref_counted.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/memory/weak_ptr.h"
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace base {
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class SingleThreadTaskRunner;
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace base
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace forwarder2 {
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Helper template class to be used in the following case:
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   * T is the type of an object that implements some work through an internal
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     or worker thread.
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   * T wants the internal thread to invoke deletion of its own instance, on
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     the thread where the instance was created.
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// To make this easier, do something like:
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   1) Add a SelfDeleteHelper<T> member to your class T, and default-initialize
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//      it in its constructor.
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   2) In the internal thread, to trigger self-deletion, call the
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//      MaybeDeleteSoon() method on this member.
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// MaybeDeleteSoon() posts a task on the message loop where the T instance was
39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// created to delete it. The task will be safely ignored if the instance is
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// otherwise deleted.
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Usage example:
43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// class Object {
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//  public:
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   typedef base::Callback<void (scoped_ptr<Object>)> ErrorCallback;
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   Object(const ErrorCallback& error_callback)
48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//       : self_deleter_helper_(this, error_callback) {
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   }
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   void StartWork() {
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     // Post a callback to DoSomethingOnWorkerThread() below to another
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     // thread.
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   }
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   void DoSomethingOnWorkerThread() {
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     ...
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     if (error_happened)
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//       self_deleter_helper_.MaybeDeleteSoon();
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   }
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//  private:
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   SelfDeleterHelper<MySelfDeletingClass> self_deleter_helper_;
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// };
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// class ObjectOwner {
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//  public:
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   ObjectOwner()
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//      : object_(new Object(base::Bind(&ObjectOwner::DeleteObjectOnError,
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//                                      base::Unretained(this))) {
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//      // To keep this example simple base::Unretained(this) is used above but
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//      // note that in a real world scenario the client would have to make sure
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//      // that the ObjectOwner instance is still alive when
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//      // DeleteObjectOnError() gets called below. This can be achieved by
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//      // using a WeakPtr<ObjectOwner> for instance.
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   }
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   void StartWork() {
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     object_->StartWork();
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   }
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//  private:
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   void DeleteObjectOnError(scoped_ptr<Object> object) {
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     DCHECK(thread_checker_.CalledOnValidThread());
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     DCHECK_EQ(object_, object);
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     // Do some extra work with |object| before it gets deleted...
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     object_.reset();
88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//     ignore_result(object.release());
89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   }
90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   base::ThreadChecker thread_checker_;
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//   scoped_ptr<Object> object_;
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// };
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)template <typename T>
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class SelfDeleterHelper {
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) public:
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  typedef base::Callback<void (scoped_ptr<T>)> DeletionCallback;
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  SelfDeleterHelper(T* self_deleting_object,
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                    const DeletionCallback& deletion_callback)
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : construction_runner_(base::MessageLoopProxy::current()),
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        self_deleting_object_(self_deleting_object),
1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        deletion_callback_(deletion_callback),
1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        weak_ptr_factory_(this) {
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ~SelfDeleterHelper() {
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(construction_runner_->RunsTasksOnCurrentThread());
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void MaybeSelfDeleteSoon() {
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(!construction_runner_->RunsTasksOnCurrentThread());
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    construction_runner_->PostTask(
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        FROM_HERE,
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::Bind(&SelfDeleterHelper::SelfDelete,
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) private:
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void SelfDelete() {
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(construction_runner_->RunsTasksOnCurrentThread());
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    deletion_callback_.Run(make_scoped_ptr(self_deleting_object_));
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const scoped_refptr<base::SingleThreadTaskRunner> construction_runner_;
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  T* const self_deleting_object_;
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const DeletionCallback deletion_callback_;
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  //WeakPtrFactory's documentation says:
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Member variables should appear before the WeakPtrFactory, to ensure
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // that any WeakPtrs to Controller are invalidated before its members
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // variable's destructors are executed, rendering them invalid.
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::WeakPtrFactory<SelfDeleterHelper<T> > weak_ptr_factory_;
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SelfDeleterHelper);
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)};
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}  // namespace forwarder2
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif  // TOOLS_ANDROID_FORWARDER2_SELF_DELETER_HELPER_H_
142