Tinker with SkLazyFnPtr a bit.

I moved the choice function from a get() arg to a template parameter.

I think this removes some of the overemphasis on "choose" from the call
site, making it a bit more clear it's normally very cheap.

It's also now more in line with what I'm thinking now for the general
SkLazyPtr<T>, which needs a "create" parameter just like SkLazyFnPtr's
"choose", but also a "destroy" that it might use both in .get() but also
at process exit.  That "destroy" needs to be made part of the type to be
called at exit, so might as well make "create" and "choose" template
parameters too so it's all consistent.

Also, add (C).

BUG=skia:
R=bungeman@google.com, mtklein@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/298393005

git-svn-id: http://skia.googlecode.com/svn/trunk@14971 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-05-29 18:29:48 +00:00
Родитель 448e2a3b39
Коммит d3c6b3f1c8
2 изменённых файлов: 38 добавлений и 23 удалений

Просмотреть файл

@ -1,3 +1,10 @@
/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkLazyFnPtr_DEFINED
#define SkLazyFnPtr_DEFINED
@ -10,8 +17,8 @@
* static FooImpl choose_foo() { return ... };
*
* int Foo(int a, int b) {
* SK_DECLARE_STATIC_LAZY_FN_PTR(FooImpl, choice);
* return choice.get(choose_foo)(a, b);
* SK_DECLARE_STATIC_LAZY_FN_PTR(FooImpl, foo, choose_foo);
* return foo.get()(a, b);
* }
*
* You can think of SK_DECLARE_STATIC_LAZY_FN_PTR as a cheaper specialization of SkOnce.
@ -19,7 +26,7 @@
*
* This must be used in a global or function scope, not as a class member.
*/
#define SK_DECLARE_STATIC_LAZY_FN_PTR(F, name) static Private::SkLazyFnPtr<F> name = { NULL }
#define SK_DECLARE_STATIC_LAZY_FN_PTR(F, name, Choose) static Private::SkLazyFnPtr<F, Choose> name
// Everything below here is private implementation details. Don't touch, don't even look.
@ -29,10 +36,11 @@
namespace Private {
// This has no constructor and is link-time initialized, so its members must be public.
template <typename F>
struct SkLazyFnPtr {
F get(F (*choose)()) {
// This has no constructor and must be zero-initialized (the macro above does this).
template <typename F, F (*Choose)()>
class SkLazyFnPtr {
public:
F get() {
// First, try reading to see if it's already set.
F fn = (F)SK_ANNOTATE_UNPROTECTED_READ(fPtr);
if (fn != NULL) {
@ -40,7 +48,7 @@ struct SkLazyFnPtr {
}
// We think it's not already set.
fn = choose();
fn = Choose();
// No particular memory barriers needed; we're not guarding anything but the pointer itself.
F prev = (F)sk_atomic_cas(&fPtr, NULL, (void*)fn);
@ -50,6 +58,7 @@ struct SkLazyFnPtr {
return prev != NULL ? prev : fn;
}
private:
void* fPtr;
};

Просмотреть файл

@ -113,34 +113,40 @@ static void sk_memcpy32_portable(uint32_t dst[], const uint32_t src[], int count
memcpy(dst, src, count * sizeof(uint32_t));
}
static SkMemset16Proc choose_memset16() {
namespace {
// These three methods technically need external linkage to be passed as template parameters.
// Since they can't be static, we hide them in an anonymous namespace instead.
SkMemset16Proc choose_memset16() {
SkMemset16Proc proc = SkMemset16GetPlatformProc();
return proc ? proc : sk_memset16_portable;
}
void sk_memset16(uint16_t dst[], uint16_t value, int count) {
SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemset16Proc, choice);
return choice.get(choose_memset16)(dst, value, count);
}
static SkMemset32Proc choose_memset32() {
SkMemset32Proc choose_memset32() {
SkMemset32Proc proc = SkMemset32GetPlatformProc();
return proc ? proc : sk_memset32_portable;
}
void sk_memset32(uint32_t dst[], uint32_t value, int count) {
SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemset32Proc, choice);
return choice.get(choose_memset32)(dst, value, count);
}
static SkMemcpy32Proc choose_memcpy32() {
SkMemcpy32Proc choose_memcpy32() {
SkMemcpy32Proc proc = SkMemcpy32GetPlatformProc();
return proc ? proc : sk_memcpy32_portable;
}
} // namespace
void sk_memset16(uint16_t dst[], uint16_t value, int count) {
SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemset16Proc, proc, choose_memset16);
proc.get()(dst, value, count);
}
void sk_memset32(uint32_t dst[], uint32_t value, int count) {
SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemset32Proc, proc, choose_memset32);
proc.get()(dst, value, count);
}
void sk_memcpy32(uint32_t dst[], const uint32_t src[], int count) {
SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemcpy32Proc, choice);
return choice.get(choose_memcpy32)(dst, src, count);
SK_DECLARE_STATIC_LAZY_FN_PTR(SkMemcpy32Proc, proc, choose_memcpy32);
proc.get()(dst, src, count);
}
///////////////////////////////////////////////////////////////////////////////