File: icon_cache.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (134 lines) | stat: -rw-r--r-- 4,783 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_ICON_CACHE_H_
#define COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_ICON_CACHE_H_

#include <map>
#include <memory>
#include <string>

#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "components/services/app_service/public/cpp/icon_loader.h"
#include "ui/gfx/image/image_skia.h"

namespace apps {

// This is used for logging, so do not remove or reorder existing entries.
enum class IconLoadingMethod {
  kFromCache = 0,
  kViaMojomCall = 1,
  kViaNonMojomCall = 2,

  // Add any new values above this one, and update kMaxValue to the highest
  // enumerator value.
  kMaxValue = kViaNonMojomCall,
};

// Records metrics when loading icons.
void RecordIconLoadMethodMetrics(IconLoadingMethod icon_loading_method);

// An IconLoader that caches the apps::mojom::IconType::kUncompressed
// results of another (wrapped) IconLoader.
class IconCache : public IconLoader {
 public:
  // What triggers dropping no-longer-used icons from the cache.
  //
  // If unsure of which one to use, kEager is a safe choice, with little
  // overhead above not having an icon cache at all.
  enum class GarbageCollectionPolicy {
    // kEager means that we drop icons as soon as their ref-count hits zero
    // (i.e. all the IconLoader::Releaser's returned by LoadIconFromIconKey
    // have been destroyed).
    //
    // This minimizes the overall memory cost of the cache. Only icons that are
    // still actively used stay alive in the cache.
    //
    // On the other hand, this can result in more cache misses than other
    // policies. For example, suppose that some UI starts with a widget showing
    // the "foo" app icon. In response to user input, the UI destroys that
    // widget and then creates a new widget to show the same "foo" app icon.
    // With a kEager garbage collection policy, that freshly created widget
    // might not get a cache hit, if the icon's ref-count hits zero in between
    // the two widgets' destruction and creation.
    kEager,

    // kExplicit means that icons can remain in the cache, even if their
    // ref-count hits zero. Instead, explicit calls to SweepReleasedIcons are
    // needed to clear cache entries.
    //
    // This can use more memory than kEager, but it can also provide a cache
    // hit in the "destroy and then create" example described above.
    //
    // On the other hand, it requires more effort and more thought from the
    // programmer. They need to make additional calls (to SweepReleasedIcons),
    // so they can't just drop an IconCache in transparently. The programmer
    // also needs to think about when is a good time to make those calls. Too
    // frequent, and you get extra complexity for not much more benefit than
    // using kEager. Too infrequent, and you have the memory cost of keeping
    // unused icons around.
    //
    // All together, kExplicit might not be the best policy for e.g. a
    // process-wide icon cache with many clients, each with different usage
    // patterns.
    kExplicit,
  };

  IconCache(IconLoader* wrapped_loader, GarbageCollectionPolicy gc_policy);

  IconCache(const IconCache&) = delete;
  IconCache& operator=(const IconCache&) = delete;

  ~IconCache() override;

  // IconLoader overrides.
  std::optional<IconKey> GetIconKey(const std::string& id) override;
  std::unique_ptr<Releaser> LoadIconFromIconKey(
      const std::string& id,
      const IconKey& icon_key,
      IconType icon_type,
      int32_t size_hint_in_dip,
      bool allow_placeholder_icon,
      apps::LoadIconCallback callback) override;

  // A hint that now is a good time to garbage-collect any icons that are not
  // actively held.
  void SweepReleasedIcons();

  void RemoveIcon(const std::string& id);

 private:
  class Value {
   public:
    gfx::ImageSkia image_;
    bool is_placeholder_icon_;
    uint64_t ref_count_;

    Value();

    IconValuePtr AsIconValue(IconType icon_type);
  };

  void Update(const IconLoader::Key& key, const IconValue& icon_value);
  void OnLoadIcon(const IconLoader::Key& key,
                  apps::LoadIconCallback callback,
                  IconValuePtr icon_value);

  void OnRelease(IconLoader::Key);

  std::map<IconLoader::Key, Value> map_;
  raw_ptr<IconLoader, DanglingUntriaged> wrapped_loader_;
  GarbageCollectionPolicy gc_policy_;

  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<IconCache> weak_ptr_factory_{this};
};

}  // namespace apps

#endif  // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_ICON_CACHE_H_