1// Copyright (c) 2012 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 BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ 6#define BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ 7 8#include "base/basictypes.h" 9#include "base/debug/alias.h" 10 11// TODO(akalin): Investigate whether it's possible to just have 12// SequencedTaskRunner use these helpers (instead of MessageLoop). 13// Then we can just move these to sequenced_task_runner.h. 14 15namespace tracked_objects { 16class Location; 17} 18 19namespace base { 20 21namespace subtle { 22template <class T, class R> class DeleteHelperInternal; 23template <class T, class R> class ReleaseHelperInternal; 24} 25 26// Template helpers which use function indirection to erase T from the 27// function signature while still remembering it so we can call the 28// correct destructor/release function. 29// 30// We use this trick so we don't need to include bind.h in a header 31// file like sequenced_task_runner.h. We also wrap the helpers in a 32// templated class to make it easier for users of DeleteSoon to 33// declare the helper as a friend. 34template <class T> 35class DeleteHelper { 36 private: 37 template <class T2, class R> friend class subtle::DeleteHelperInternal; 38 39 static void DoDelete(const void* object) { 40 delete reinterpret_cast<const T*>(object); 41 } 42 43 DISALLOW_COPY_AND_ASSIGN(DeleteHelper); 44}; 45 46template <class T> 47class ReleaseHelper { 48 private: 49 template <class T2, class R> friend class subtle::ReleaseHelperInternal; 50 51 static void DoRelease(const void* object) { 52 reinterpret_cast<const T*>(object)->Release(); 53 } 54 55 DISALLOW_COPY_AND_ASSIGN(ReleaseHelper); 56}; 57 58namespace subtle { 59 60// An internal SequencedTaskRunner-like class helper for DeleteHelper 61// and ReleaseHelper. We don't want to expose the Do*() functions 62// directly directly since the void* argument makes it possible to 63// pass/ an object of the wrong type to delete. Instead, we force 64// callers to go through these internal helpers for type 65// safety. SequencedTaskRunner-like classes which expose DeleteSoon or 66// ReleaseSoon methods should friend the appropriate helper and 67// implement a corresponding *Internal method with the following 68// signature: 69// 70// bool(const tracked_objects::Location&, 71// void(*function)(const void*), 72// void* object) 73// 74// An implementation of this function should simply create a 75// base::Closure from (function, object) and return the result of 76// posting the task. 77template <class T, class ReturnType> 78class DeleteHelperInternal { 79 public: 80 template <class SequencedTaskRunnerType> 81 static ReturnType DeleteViaSequencedTaskRunner( 82 SequencedTaskRunnerType* sequenced_task_runner, 83 const tracked_objects::Location& from_here, 84 const T* object) { 85 return sequenced_task_runner->DeleteSoonInternal( 86 from_here, &DeleteHelper<T>::DoDelete, object); 87 } 88 89 private: 90 DISALLOW_COPY_AND_ASSIGN(DeleteHelperInternal); 91}; 92 93template <class T, class ReturnType> 94class ReleaseHelperInternal { 95 public: 96 template <class SequencedTaskRunnerType> 97 static ReturnType ReleaseViaSequencedTaskRunner( 98 SequencedTaskRunnerType* sequenced_task_runner, 99 const tracked_objects::Location& from_here, 100 const T* object) { 101 return sequenced_task_runner->ReleaseSoonInternal( 102 from_here, &ReleaseHelper<T>::DoRelease, object); 103 } 104 105 private: 106 DISALLOW_COPY_AND_ASSIGN(ReleaseHelperInternal); 107}; 108 109} // namespace subtle 110 111} // namespace base 112 113#endif // BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ 114