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 STORAGE_BROWSER_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_
6#define STORAGE_BROWSER_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_
7
8#include <map>
9
10#include "base/basictypes.h"
11#include "base/bind.h"
12#include "base/memory/ref_counted.h"
13#include "base/sequenced_task_runner.h"
14#include "base/threading/thread.h"
15
16namespace storage {
17
18// A wrapper for dispatching method.
19template <class T, class Method, class Params>
20void NotifyWrapper(T obj, Method m, const Params& p) {
21  DispatchToMethod(base::internal::UnwrapTraits<T>::Unwrap(obj), m, p);
22}
23
24// An observer list helper to notify on a given task runner.
25// Observer pointers (stored as ObserverStoreType) must be kept alive
26// until this list dispatches all the notifications.
27//
28// Unlike regular ObserverList or ObserverListThreadSafe internal observer
29// list is immutable (though not declared const) and cannot be modified after
30// constructed.
31//
32// It is ok to specify scoped_refptr<Observer> as ObserverStoreType to
33// explicitly keep references if necessary.
34template <class Observer, class ObserverStoreType = Observer*>
35class TaskRunnerBoundObserverList {
36 public:
37  typedef scoped_refptr<base::SequencedTaskRunner> TaskRunnerPtr;
38  typedef std::map<ObserverStoreType, TaskRunnerPtr> ObserversListMap;
39
40  // Creates an empty list.
41  TaskRunnerBoundObserverList<Observer, ObserverStoreType>() {}
42
43  // Creates a new list with given |observers|.
44  explicit TaskRunnerBoundObserverList<Observer, ObserverStoreType>(
45      const ObserversListMap& observers)
46      : observers_(observers) {}
47
48  virtual ~TaskRunnerBoundObserverList<Observer, ObserverStoreType>() {}
49
50  // Returns a new observer list with given observer.
51  // It is valid to give NULL as |runner_to_notify|, and in that case
52  // notifications are dispatched on the current runner.
53  // Note that this is a const method and does NOT change 'this' observer
54  // list but returns a new list.
55  TaskRunnerBoundObserverList<Observer, ObserverStoreType> AddObserver(
56      Observer* observer,
57      base::SequencedTaskRunner* runner_to_notify) const {
58    ObserversListMap observers = observers_;
59    observers.insert(std::make_pair(observer, runner_to_notify));
60    return TaskRunnerBoundObserverList<Observer, ObserverStoreType>(observers);
61  }
62
63  // Notify on the task runner that is given to AddObserver.
64  // If we're already on the runner this just dispatches the method.
65  template <class Method, class Params>
66  void Notify(Method method, const Params& params) const {
67    COMPILE_ASSERT(
68        (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value),
69        badunboundmethodparams);
70    for (typename ObserversListMap::const_iterator it = observers_.begin();
71         it != observers_.end(); ++it) {
72      if (!it->second.get() || it->second->RunsTasksOnCurrentThread()) {
73        DispatchToMethod(UnwrapTraits::Unwrap(it->first), method, params);
74        continue;
75      }
76      it->second->PostTask(
77          FROM_HERE,
78          base::Bind(&NotifyWrapper<ObserverStoreType, Method, Params>,
79                     it->first, method, params));
80    }
81  }
82
83 private:
84  typedef base::internal::UnwrapTraits<ObserverStoreType> UnwrapTraits;
85
86  ObserversListMap observers_;
87};
88
89class FileAccessObserver;
90class FileChangeObserver;
91class FileUpdateObserver;
92
93typedef TaskRunnerBoundObserverList<FileAccessObserver> AccessObserverList;
94typedef TaskRunnerBoundObserverList<FileChangeObserver> ChangeObserverList;
95typedef TaskRunnerBoundObserverList<FileUpdateObserver> UpdateObserverList;
96
97}  // namespace storage
98
99#endif  // STORAGE_BROWSER_FILEAPI_TASK_RUNNER_BOUND_OBSERVER_LIST_H_
100