// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef WEBKIT_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_ #define WEBKIT_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_ #include #include "base/basictypes.h" #include "base/bind.h" #include "base/memory/ref_counted.h" #include "base/sequenced_task_runner.h" #include "base/threading/thread.h" namespace fileapi { // A wrapper for dispatching method. template void NotifyWrapper(T obj, Method m, const Params& p) { DispatchToMethod(base::internal::UnwrapTraits::Unwrap(obj), m, p); } // An observer list helper to notify on a given task runner. // Observer pointers (stored as ObserverStoreType) must be kept alive // until this list dispatches all the notifications. // // Unlike regular ObserverList or ObserverListThreadSafe internal observer // list is immutable (though not declared const) and cannot be modified after // constructed. // // It is ok to specify scoped_refptr as ObserverStoreType to // explicitly keep references if necessary. template class TaskRunnerBoundObserverList { public: // A constructor parameter class. class Source { public: typedef scoped_refptr TaskRunnerPtr; typedef std::map ObserversListMap; // Add |observer| to the list parameter. The |observer| will be notified on // the |runner_to_notify| runner. It is valid to give NULL as // |runner_to_notify| (in such case notifications are dispatched on // the current runner). void AddObserver(Observer* observer, base::SequencedTaskRunner* runner_to_notify) { observers_.insert(std::make_pair(observer, runner_to_notify)); } const ObserversListMap& observers() const { return observers_; } private: ObserversListMap observers_; }; // Creates an empty list. TaskRunnerBoundObserverList() {} // Creates a new list with given |observers_param|. explicit TaskRunnerBoundObserverList( const Source& observers) : source_(observers) {} virtual ~TaskRunnerBoundObserverList() {} // Notify on the task runner that is given to AddObserver. // If we're already on the runner this just dispatches the method. template void Notify(Method method, const Params& params) const { COMPILE_ASSERT( (base::internal::ParamsUseScopedRefptrCorrectly::value), badunboundmethodparams); for (typename ObserversListMap::const_iterator it = source_.observers().begin(); it != source_.observers().end(); ++it) { if (!it->second.get() || it->second->RunsTasksOnCurrentThread()) { DispatchToMethod(UnwrapTraits::Unwrap(it->first), method, params); continue; } it->second->PostTask( FROM_HERE, base::Bind(&NotifyWrapper, it->first, method, params)); } } const Source& source() const { return source_; } private: typedef base::internal::UnwrapTraits UnwrapTraits; typedef scoped_refptr TaskRunnerPtr; typedef std::map ObserversListMap; Source source_; }; class FileAccessObserver; class FileChangeObserver; class FileUpdateObserver; typedef TaskRunnerBoundObserverList AccessObserverList; typedef TaskRunnerBoundObserverList ChangeObserverList; typedef TaskRunnerBoundObserverList UpdateObserverList; } // namespace fileapi #endif // WEBKIT_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_