Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(81)

Side by Side Diff: src/core/SkFunction.h

Issue 1048243002: small-object optimization for SkFunction (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: windows Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/utils/SkTLogic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkFunction_DEFINED 8 #ifndef SkFunction_DEFINED
9 #define SkFunction_DEFINED 9 #define SkFunction_DEFINED
10 10
11 // TODO: document 11 // TODO: document
12 12
13 #include "SkTypes.h" 13 #include "SkTypes.h"
14 #include "SkTLogic.h"
14 15
15 template <typename> class SkFunction; 16 template <typename> class SkFunction;
16 17
17 template <typename R, typename... Args> 18 template <typename R, typename... Args>
18 class SkFunction<R(Args...)> : SkNoncopyable { 19 class SkFunction<R(Args...)> : SkNoncopyable {
19 public: 20 public:
20 explicit SkFunction(R (*fn)(Args...)) : fVTable(GetFunctionPointerVTable()) { 21 explicit SkFunction(R (*fn)(Args...)) : fVTable(GetFunctionPointerVTable()) {
21 // We've been passed a function pointer. We'll just store it. 22 // We've been passed a function pointer. We'll just store it.
22 fFunction = reinterpret_cast<void*>(fn); 23 fFunction = reinterpret_cast<void*>(fn);
23 } 24 }
24 25
25 template <typename Fn> 26 template <typename Fn>
26 explicit SkFunction(Fn fn) : fVTable(GetVTable<Fn>()) { 27 explicit SkFunction(Fn fn, SK_WHEN_C((sizeof(Fn) > sizeof(void*)), void*) = nullptr)
27 // We've got a functor. The basic thing we can always do is copy it ont o the heap. 28 : fVTable(GetOutlineVTable<Fn>()) {
29 // We've got a functor larger than a pointer. We've go to copy it onto the heap.
28 fFunction = SkNEW_ARGS(Fn, (fn)); 30 fFunction = SkNEW_ARGS(Fn, (fn));
29 } 31 }
30 32
31 ~SkFunction() { fVTable.fDelete(fFunction); } 33 template <typename Fn>
34 explicit SkFunction(Fn fn, SK_WHEN_C((sizeof(Fn) <= sizeof(void*)), void*) = nullptr)
35 : fVTable(GetInlineVTable<Fn>()) {
36 // We've got a functor that fits in a pointer. We copy it right inline.
37 SkNEW_PLACEMENT_ARGS(&fFunction, Fn, (fn));
38 }
39
40 ~SkFunction() { fVTable.fCleanUp(fFunction); }
32 41
33 R operator()(Args... args) { return fVTable.fCall(fFunction, args...); } 42 R operator()(Args... args) { return fVTable.fCall(fFunction, args...); }
34 43
35 private: 44 private:
36 struct VTable { 45 struct VTable {
37 R (*fCall)(void*, Args...); 46 R (*fCall)(void*, Args...);
38 void (*fDelete)(void*); 47 void (*fCleanUp)(void*);
39 }; 48 };
40 49
50 // Used when fFunction is a function pointer of type R(*)(Args...).
41 static const VTable& GetFunctionPointerVTable() { 51 static const VTable& GetFunctionPointerVTable() {
42 static const VTable vtable = { 52 static const VTable vtable = {
43 [](void* fn, Args... args) { return reinterpret_cast<R(*)(Args...)>( fn)(args...); }, 53 [](void* fn, Args... args) { return reinterpret_cast<R(*)(Args...)>( fn)(args...); },
44 [](void*) { /* Don't delete function pointers. */ }, 54 [](void*) { /* Nothing to clean up for function pointers. */ }
45 }; 55 };
46 return vtable; 56 return vtable;
47 } 57 }
48 58
59 // Used when fFunction is a pointer to a functor of type Fn on the heap (we own it).
49 template <typename Fn> 60 template <typename Fn>
50 static const VTable& GetVTable() { 61 static const VTable& GetOutlineVTable() {
51 static const VTable vtable = { 62 static const VTable vtable = {
52 [](void* fn, Args... args) { return (*static_cast<Fn*>(fn))(args...) ; }, 63 [](void* fn, Args... args) { return (*static_cast<Fn*>(fn))(args...) ; },
53 [](void* fn) { SkDELETE(static_cast<Fn*>(fn)); }, 64 [](void* fn) { SkDELETE(static_cast<Fn*>(fn)); },
54 }; 65 };
55 return vtable; 66 return vtable;
56 } 67 }
57 68
58 void* fFunction; // Either a function pointer, or a pointer to a func tor. 69 // Used when fFunction _is_ a functor of type Fn, not a pointer to the funct or.
70 template <typename Fn>
71 static const VTable& GetInlineVTable() {
72 static const VTable vtable = {
73 [](void* fn, Args... args) {
74 union { void* p; Fn f; } pun = { fn };
75 return pun.f(args...);
76 },
77 [](void* fn) {
78 union { void* p; Fn f; } pun = { fn };
79 pun.f.~Fn();
80 (void)(pun.f); // Otherwise, when ~Fn() is trivial, MSVC compl ains pun is unused.
81 }
82 };
83 return vtable;
84 }
85
86
87 void* fFunction; // A function pointer, a pointer to a functor, or an inlined functor.
59 const VTable& fVTable; // How to call, delete (and one day copy, move) fFun ction. 88 const VTable& fVTable; // How to call, delete (and one day copy, move) fFun ction.
60 }; 89 };
61 90
62 // TODO: 91 // TODO:
63 // - is it worth moving fCall out of the VTable into SkFunction itself to avoi d the indirection? 92 // - is it worth moving fCall out of the VTable into SkFunction itself to avoi d the indirection?
64 // - should constructors be implicit? 93 // - should constructors be implicit?
65 // - make SkFunction copyable 94 // - make SkFunction copyable
66 // - emulate std::forward for moveable functors (e.g. lambdas) 95 // - emulate std::forward for moveable functors (e.g. lambdas)
67 // - forward args too? 96 // - forward args too?
68 // - implement small-object optimization to store functors inline
69 97
70 #endif//SkFunction_DEFINED 98 #endif//SkFunction_DEFINED
OLDNEW
« no previous file with comments | « no previous file | src/utils/SkTLogic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698