blob: 856b83ce4c0ad6fc28b930ff174e6a74af1d8610 [file] [log] [blame]
reed9d93c2e2014-10-08 05:17:12 -07001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkRefCnt.h"
9#include "include/core/SkTypes.h"
10#include "include/private/SkMalloc.h"
11#include "src/core/SkCachedData.h"
12#include "src/lazy/SkDiscardableMemoryPool.h"
13#include "tests/Test.h"
reed9d93c2e2014-10-08 05:17:12 -070014
Ben Wagnerb607a8f2018-03-12 13:46:21 -040015#include <cstring>
16
17class SkDiscardableMemory;
18
reed9d93c2e2014-10-08 05:17:12 -070019enum LockedState {
20 kUnlocked,
21 kLocked,
22};
23
24enum CachedState {
25 kNotInCache,
26 kInCache,
27};
28
29static void check_data(skiatest::Reporter* reporter, SkCachedData* data,
30 int refcnt, CachedState cacheState, LockedState lockedState) {
31 REPORTER_ASSERT(reporter, data->testing_only_getRefCnt() == refcnt);
32 REPORTER_ASSERT(reporter, data->testing_only_isInCache() == (kInCache == cacheState));
33 REPORTER_ASSERT(reporter, data->testing_only_isLocked() == (lockedState == kLocked));
34}
35
36static SkCachedData* make_data(size_t size, SkDiscardableMemoryPool* pool) {
37 if (pool) {
38 SkDiscardableMemory* dm = pool->create(size);
39 // the pool "can" return null, but it shouldn't in these controlled conditions
djsollenf2b340f2016-01-29 08:51:04 -080040 SkASSERT_RELEASE(dm);
halcanary385fe4d2015-08-26 13:07:48 -070041 return new SkCachedData(size, dm);
reed9d93c2e2014-10-08 05:17:12 -070042 } else {
halcanary385fe4d2015-08-26 13:07:48 -070043 return new SkCachedData(sk_malloc_throw(size), size);
reed9d93c2e2014-10-08 05:17:12 -070044 }
45}
46
47// returns with the data locked by client and cache
48static SkCachedData* test_locking(skiatest::Reporter* reporter,
49 size_t size, SkDiscardableMemoryPool* pool) {
50 SkCachedData* data = make_data(size, pool);
halcanary9d524f22016-03-29 09:03:52 -070051
reed9d93c2e2014-10-08 05:17:12 -070052 memset(data->writable_data(), 0x80, size); // just to use writable_data()
53
54 check_data(reporter, data, 1, kNotInCache, kLocked);
halcanary9d524f22016-03-29 09:03:52 -070055
reed9d93c2e2014-10-08 05:17:12 -070056 data->ref();
57 check_data(reporter, data, 2, kNotInCache, kLocked);
58 data->unref();
59 check_data(reporter, data, 1, kNotInCache, kLocked);
halcanary9d524f22016-03-29 09:03:52 -070060
reed9d93c2e2014-10-08 05:17:12 -070061 data->attachToCacheAndRef();
62 check_data(reporter, data, 2, kInCache, kLocked);
halcanary9d524f22016-03-29 09:03:52 -070063
reed9d93c2e2014-10-08 05:17:12 -070064 data->unref();
65 check_data(reporter, data, 1, kInCache, kUnlocked);
halcanary9d524f22016-03-29 09:03:52 -070066
reed9d93c2e2014-10-08 05:17:12 -070067 data->ref();
68 check_data(reporter, data, 2, kInCache, kLocked);
69
70 return data;
71}
72
73/*
74 * SkCachedData behaves differently (regarding its locked/unlocked state) depending on
75 * when it is in the cache or not. Being in the cache is signaled by calling attachToCacheAndRef()
76 * instead of ref(). (and balanced by detachFromCacheAndUnref).
77 *
78 * Thus, among other things, we test the end-of-life behavior when the client is the last owner
79 * and when the cache is.
80 */
81DEF_TEST(CachedData, reporter) {
Hal Canarya294be22017-04-19 13:17:59 -040082 sk_sp<SkDiscardableMemoryPool> pool(SkDiscardableMemoryPool::Make(1000));
reed9d93c2e2014-10-08 05:17:12 -070083
84 for (int useDiscardable = 0; useDiscardable <= 1; ++useDiscardable) {
85 const size_t size = 100;
86
87 // test with client as last owner
halcanary96fcdcc2015-08-27 07:41:13 -070088 SkCachedData* data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr);
reed9d93c2e2014-10-08 05:17:12 -070089 check_data(reporter, data, 2, kInCache, kLocked);
90 data->detachFromCacheAndUnref();
91 check_data(reporter, data, 1, kNotInCache, kLocked);
92 data->unref();
93
94 // test with cache as last owner
halcanary96fcdcc2015-08-27 07:41:13 -070095 data = test_locking(reporter, size, useDiscardable ? pool.get() : nullptr);
reed9d93c2e2014-10-08 05:17:12 -070096 check_data(reporter, data, 2, kInCache, kLocked);
97 data->unref();
98 check_data(reporter, data, 1, kInCache, kUnlocked);
99 data->detachFromCacheAndUnref();
100 }
101}