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