1 /* 2 * Copyright 2012 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 8 #include "SkRefCnt.h" 9 #include "SkThreadUtils.h" 10 #include "SkTypes.h" 11 #include "SkWeakRefCnt.h" 12 #include "Test.h" 13 14 static void bounce_ref(void* data) { 15 SkRefCnt* ref = static_cast<SkRefCnt*>(data); 16 for (int i = 0; i < 100000; ++i) { 17 ref->ref(); 18 ref->unref(); 19 } 20 } 21 22 static void test_refCnt(skiatest::Reporter* reporter) { 23 SkRefCnt* ref = new SkRefCnt(); 24 25 SkThread thing1(bounce_ref, ref); 26 SkThread thing2(bounce_ref, ref); 27 28 SkAssertResult(thing1.start()); 29 SkAssertResult(thing2.start()); 30 31 thing1.join(); 32 thing2.join(); 33 34 REPORTER_ASSERT(reporter, ref->unique()); 35 ref->unref(); 36 } 37 38 static void bounce_weak_ref(void* data) { 39 SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data); 40 for (int i = 0; i < 100000; ++i) { 41 if (ref->try_ref()) { 42 ref->unref(); 43 } 44 } 45 } 46 47 static void bounce_weak_weak_ref(void* data) { 48 SkWeakRefCnt* ref = static_cast<SkWeakRefCnt*>(data); 49 for (int i = 0; i < 100000; ++i) { 50 ref->weak_ref(); 51 ref->weak_unref(); 52 } 53 } 54 55 static void test_weakRefCnt(skiatest::Reporter* reporter) { 56 SkWeakRefCnt* ref = new SkWeakRefCnt(); 57 58 SkThread thing1(bounce_ref, ref); 59 SkThread thing2(bounce_ref, ref); 60 SkThread thing3(bounce_weak_ref, ref); 61 SkThread thing4(bounce_weak_weak_ref, ref); 62 63 SkAssertResult(thing1.start()); 64 SkAssertResult(thing2.start()); 65 SkAssertResult(thing3.start()); 66 SkAssertResult(thing4.start()); 67 68 thing1.join(); 69 thing2.join(); 70 thing3.join(); 71 thing4.join(); 72 73 REPORTER_ASSERT(reporter, ref->unique()); 74 SkDEBUGCODE(REPORTER_ASSERT(reporter, ref->getWeakCnt() == 1)); 75 ref->unref(); 76 } 77 78 DEF_TEST(RefCnt, reporter) { 79 test_refCnt(reporter); 80 test_weakRefCnt(reporter); 81 } 82 83 /////////////////////////////////////////////////////////////////////////////////////////////////// 84 85 static int gRefCounter; 86 static int gUnrefCounter; 87 static int gNewCounter; 88 static int gDeleteCounter; 89 90 #define check(reporter, ref, unref, make, kill) \ 91 REPORTER_ASSERT(reporter, gRefCounter == ref); \ 92 REPORTER_ASSERT(reporter, gUnrefCounter == unref); \ 93 REPORTER_ASSERT(reporter, gNewCounter == make); \ 94 REPORTER_ASSERT(reporter, gDeleteCounter == kill); 95 96 97 class Effect { 98 public: 99 Effect() : fRefCnt(1) { 100 gNewCounter += 1; 101 } 102 virtual ~Effect() {} 103 104 int fRefCnt; 105 106 void ref() { 107 gRefCounter += 1; 108 fRefCnt += 1; 109 } 110 void unref() { 111 gUnrefCounter += 1; 112 113 SkASSERT(fRefCnt > 0); 114 if (0 == --fRefCnt) { 115 gDeleteCounter += 1; 116 delete this; 117 } 118 } 119 120 int* method() const { return new int; } 121 }; 122 123 static sk_sp<Effect> Create() { 124 return sk_make_sp<Effect>(); 125 } 126 127 class Paint { 128 public: 129 sk_sp<Effect> fEffect; 130 131 const sk_sp<Effect>& get() const { return fEffect; } 132 133 void set(sk_sp<Effect> value) { 134 fEffect = std::move(value); 135 } 136 }; 137 138 struct EffectImpl : public Effect { 139 ~EffectImpl() override {} 140 141 static sk_sp<EffectImpl> Create() { 142 return sk_sp<EffectImpl>(new EffectImpl); 143 } 144 int fValue; 145 }; 146 static sk_sp<Effect> make_effect() { 147 auto foo = EffectImpl::Create(); 148 foo->fValue = 42; 149 return std::move(foo); 150 } 151 152 static void reset_counters() { 153 gRefCounter = 0; 154 gUnrefCounter = 0; 155 gNewCounter = 0; 156 gDeleteCounter = 0; 157 } 158 DEF_TEST(sk_sp, reporter) { 159 reset_counters(); 160 161 Paint paint; 162 REPORTER_ASSERT(reporter, paint.fEffect.get() == nullptr); 163 REPORTER_ASSERT(reporter, !paint.get()); 164 check(reporter, 0, 0, 0, 0); 165 166 paint.set(Create()); 167 check(reporter, 0, 0, 1, 0); 168 REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 1); 169 170 if (paint.get()) { 171 REPORTER_ASSERT(reporter, true); 172 } else { 173 REPORTER_ASSERT(reporter, false); 174 } 175 if (!paint.get()) { 176 REPORTER_ASSERT(reporter, false); 177 } else { 178 REPORTER_ASSERT(reporter, true); 179 } 180 181 paint.set(nullptr); 182 check(reporter, 0, 1, 1, 1); 183 184 if (paint.get()) { 185 REPORTER_ASSERT(reporter, false); 186 } else { 187 REPORTER_ASSERT(reporter, true); 188 } 189 if (!paint.get()) { 190 REPORTER_ASSERT(reporter, true); 191 } else { 192 REPORTER_ASSERT(reporter, false); 193 } 194 195 auto e = Create(); 196 REPORTER_ASSERT(reporter, sizeof(e) == sizeof(void*)); 197 198 check(reporter, 0, 1, 2, 1); 199 paint.set(e); 200 check(reporter, 1, 1, 2, 1); 201 REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 2); 202 203 Paint paint2; 204 paint2.set(paint.get()); 205 check(reporter, 2, 1, 2, 1); 206 REPORTER_ASSERT(reporter, paint.fEffect.get()->fRefCnt == 3); 207 208 // Test sk_sp::operator-> 209 delete paint.get()->method(); 210 check(reporter, 2, 1, 2, 1); 211 212 // Test sk_sp::operator* 213 delete (*paint.get()).method(); 214 check(reporter, 2, 1, 2, 1); 215 216 paint.set(nullptr); 217 e = nullptr; 218 paint2.set(nullptr); 219 check(reporter, 2, 4, 2, 2); 220 221 reset_counters(); 222 { 223 // Test convertible sk_sp assignment. 224 check(reporter, 0, 0, 0, 0); 225 sk_sp<Effect> foo(nullptr); 226 REPORTER_ASSERT(reporter, !foo); 227 foo = make_effect(); 228 REPORTER_ASSERT(reporter, foo); 229 check(reporter, 0, 0, 1, 0); 230 } 231 check(reporter, 0, 1, 1, 1); 232 233 // Test passing convertible rvalue into funtion. 234 reset_counters(); 235 paint.set(EffectImpl::Create()); 236 check(reporter, 0, 0, 1, 0); 237 paint.set(nullptr); 238 check(reporter, 0, 1, 1, 1); 239 240 reset_counters(); 241 auto baz = EffectImpl::Create(); 242 check(reporter, 0, 0, 1, 0); 243 paint.set(std::move(baz)); 244 check(reporter, 0, 0, 1, 0); 245 REPORTER_ASSERT(reporter, !baz); 246 paint.set(nullptr); 247 check(reporter, 0, 1, 1, 1); 248 249 reset_counters(); 250 { 251 // test comparison operator with convertible type. 252 sk_sp<EffectImpl> bar1 = EffectImpl::Create(); 253 sk_sp<Effect> bar2(bar1); // convertible copy constructor 254 check(reporter, 1, 0, 1, 0); 255 REPORTER_ASSERT(reporter, bar1); 256 REPORTER_ASSERT(reporter, bar2); 257 REPORTER_ASSERT(reporter, bar1 == bar2); 258 REPORTER_ASSERT(reporter, bar2 == bar1); 259 REPORTER_ASSERT(reporter, !(bar1 != bar2)); 260 REPORTER_ASSERT(reporter, !(bar2 != bar1)); 261 sk_sp<Effect> bar3(nullptr); 262 bar3 = bar1; // convertible copy assignment 263 check(reporter, 2, 0, 1, 0); 264 265 } 266 check(reporter, 2, 3, 1, 1); 267 268 // test passing convertible copy into funtion. 269 reset_counters(); 270 baz = EffectImpl::Create(); 271 check(reporter, 0, 0, 1, 0); 272 paint.set(baz); 273 check(reporter, 1, 0, 1, 0); 274 baz = nullptr; 275 check(reporter, 1, 1, 1, 0); 276 paint.set(nullptr); 277 check(reporter, 1, 2, 1, 1); 278 279 { 280 sk_sp<SkRefCnt> empty; 281 sk_sp<SkRefCnt> notEmpty = sk_make_sp<SkRefCnt>(); 282 REPORTER_ASSERT(reporter, empty == sk_sp<SkRefCnt>()); 283 284 REPORTER_ASSERT(reporter, notEmpty != empty); 285 REPORTER_ASSERT(reporter, empty != notEmpty); 286 287 REPORTER_ASSERT(reporter, nullptr == empty); 288 REPORTER_ASSERT(reporter, empty == nullptr); 289 REPORTER_ASSERT(reporter, empty == empty); 290 291 REPORTER_ASSERT(reporter, nullptr <= empty); 292 REPORTER_ASSERT(reporter, empty <= nullptr); 293 REPORTER_ASSERT(reporter, empty <= empty); 294 295 REPORTER_ASSERT(reporter, nullptr >= empty); 296 REPORTER_ASSERT(reporter, empty >= nullptr); 297 REPORTER_ASSERT(reporter, empty >= empty); 298 } 299 300 { 301 sk_sp<SkRefCnt> a = sk_make_sp<SkRefCnt>(); 302 sk_sp<SkRefCnt> b = sk_make_sp<SkRefCnt>(); 303 REPORTER_ASSERT(reporter, a != b); 304 REPORTER_ASSERT(reporter, (a < b) != (b < a)); 305 REPORTER_ASSERT(reporter, (b > a) != (a > b)); 306 REPORTER_ASSERT(reporter, (a <= b) != (b <= a)); 307 REPORTER_ASSERT(reporter, (b >= a) != (a >= b)); 308 309 REPORTER_ASSERT(reporter, a == a); 310 REPORTER_ASSERT(reporter, a <= a); 311 REPORTER_ASSERT(reporter, a >= a); 312 } 313 314 // http://wg21.cmeerw.net/lwg/issue998 315 { 316 class foo : public SkRefCnt { 317 public: 318 foo() : bar(this) {} 319 void reset() { bar.reset(); } 320 private: 321 sk_sp<foo> bar; 322 }; 323 // The following should properly delete the object and not cause undefined behavior. 324 // This is an ugly example, but the same issue can arise in more subtle ways. 325 (new foo)->reset(); 326 } 327 328 // https://crrev.com/0d4ef2583a6f19c3e61be04d36eb1a60b133832c 329 { 330 struct StructB; 331 struct StructA : public SkRefCnt { 332 sk_sp<StructB> b; 333 }; 334 335 struct StructB : public SkRefCnt { 336 sk_sp<StructA> a; 337 ~StructB() override {} // Some clang versions don't emit this implicitly. 338 }; 339 340 // Create a reference cycle. 341 StructA* a = new StructA; 342 a->b.reset(new StructB); 343 a->b->a.reset(a); 344 345 // Break the cycle by calling reset(). This will cause |a| (and hence, |a.b|) 346 // to be deleted before the call to reset() returns. This tests that the 347 // implementation of sk_sp::reset() doesn't access |this| after it 348 // deletes the underlying pointer. This behaviour is consistent with the 349 // definition of unique_ptr::reset in C++11. 350 a->b.reset(); 351 } 352 } 353 354 namespace { 355 struct FooAbstract : public SkRefCnt { 356 virtual void f() = 0; 357 }; 358 struct FooConcrete : public FooAbstract { 359 void f() override {} 360 }; 361 } 362 static sk_sp<FooAbstract> make_foo() { 363 // can not cast FooConcrete to FooAbstract. 364 // can cast FooConcrete* to FooAbstract*. 365 return sk_make_sp<FooConcrete>(); 366 } 367 DEF_TEST(sk_make_sp, r) { 368 auto x = make_foo(); 369 } 370 371 // Test that reset() "adopts" ownership from the caller, even if we are given the same ptr twice 372 // 373 DEF_TEST(sk_sp_reset, r) { 374 SkRefCnt* rc = new SkRefCnt; 375 REPORTER_ASSERT(r, rc->unique()); 376 377 sk_sp<SkRefCnt> sp; 378 sp.reset(rc); 379 // We have transfered our ownership over to sp 380 REPORTER_ASSERT(r, rc->unique()); 381 382 rc->ref(); // now "rc" is also an owner 383 REPORTER_ASSERT(r, !rc->unique()); 384 385 sp.reset(rc); // this should transfer our ownership over to sp 386 REPORTER_ASSERT(r, rc->unique()); 387 } 388 389 DEF_TEST(sk_sp_ref, r) { 390 SkRefCnt* rc = new SkRefCnt; 391 REPORTER_ASSERT(r, rc->unique()); 392 393 { 394 sk_sp<SkRefCnt> sp = sk_ref_sp(rc); 395 REPORTER_ASSERT(r, !rc->unique()); 396 } 397 398 REPORTER_ASSERT(r, rc->unique()); 399 rc->unref(); 400 } 401