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