michael@0: // Copyright (c) 2012 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #ifndef BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ michael@0: #define BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_ michael@0: michael@0: #include "base/basictypes.h" michael@0: michael@0: // TODO(akalin): Investigate whether it's possible to just have michael@0: // SequencedTaskRunner use these helpers (instead of MessageLoop). michael@0: // Then we can just move these to sequenced_task_runner.h. michael@0: michael@0: namespace tracked_objects { michael@0: class Location; michael@0: } michael@0: michael@0: namespace base { michael@0: michael@0: namespace subtle { michael@0: template class DeleteHelperInternal; michael@0: template class ReleaseHelperInternal; michael@0: } michael@0: michael@0: // Template helpers which use function indirection to erase T from the michael@0: // function signature while still remembering it so we can call the michael@0: // correct destructor/release function. michael@0: // michael@0: // We use this trick so we don't need to include bind.h in a header michael@0: // file like sequenced_task_runner.h. We also wrap the helpers in a michael@0: // templated class to make it easier for users of DeleteSoon to michael@0: // declare the helper as a friend. michael@0: template michael@0: class DeleteHelper { michael@0: private: michael@0: template friend class subtle::DeleteHelperInternal; michael@0: michael@0: static void DoDelete(const void* object) { michael@0: delete reinterpret_cast(object); michael@0: } michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(DeleteHelper); michael@0: }; michael@0: michael@0: template michael@0: class ReleaseHelper { michael@0: private: michael@0: template friend class subtle::ReleaseHelperInternal; michael@0: michael@0: static void DoRelease(const void* object) { michael@0: reinterpret_cast(object)->Release(); michael@0: } michael@0: michael@0: DISALLOW_COPY_AND_ASSIGN(ReleaseHelper); michael@0: }; michael@0: michael@0: namespace subtle { michael@0: michael@0: // An internal SequencedTaskRunner-like class helper for DeleteHelper michael@0: // and ReleaseHelper. We don't want to expose the Do*() functions michael@0: // directly directly since the void* argument makes it possible to michael@0: // pass/ an object of the wrong type to delete. Instead, we force michael@0: // callers to go through these internal helpers for type michael@0: // safety. SequencedTaskRunner-like classes which expose DeleteSoon or michael@0: // ReleaseSoon methods should friend the appropriate helper and michael@0: // implement a corresponding *Internal method with the following michael@0: // signature: michael@0: // michael@0: // bool(const tracked_objects::Location&, michael@0: // void(*function)(const void*), michael@0: // void* object) michael@0: // michael@0: // An implementation of this function should simply create a michael@0: // base::Closure from (function, object) and return the result of michael@0: // posting the task. michael@0: template michael@0: class DeleteHelperInternal { michael@0: public: michael@0: template michael@0: static ReturnType DeleteViaSequencedTaskRunner( michael@0: SequencedTaskRunnerType* sequenced_task_runner, michael@0: const tracked_objects::Location& from_here, michael@0: const T* object) { michael@0: return sequenced_task_runner->DeleteSoonInternal( michael@0: from_here, &DeleteHelper::DoDelete, object); michael@0: } michael@0: michael@0: private: michael@0: DISALLOW_COPY_AND_ASSIGN(DeleteHelperInternal); michael@0: }; michael@0: michael@0: template michael@0: class ReleaseHelperInternal { michael@0: public: michael@0: template michael@0: static ReturnType ReleaseViaSequencedTaskRunner( michael@0: SequencedTaskRunnerType* sequenced_task_runner, michael@0: const tracked_objects::Location& from_here, michael@0: const T* object) { michael@0: return sequenced_task_runner->ReleaseSoonInternal( michael@0: from_here, &ReleaseHelper::DoRelease, object); michael@0: } michael@0: michael@0: private: michael@0: DISALLOW_COPY_AND_ASSIGN(ReleaseHelperInternal); michael@0: }; michael@0: michael@0: } // namespace subtle michael@0: michael@0: } // namespace base michael@0: michael@0: #endif // BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_