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

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

Issue 1824983003: SkRecord: infer return type for visit() and mutate(). (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 9 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 | « src/core/SkBigPicture.cpp ('k') | src/core/SkRecord.cpp » ('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 2014 Google Inc. 2 * Copyright 2014 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 SkRecord_DEFINED 8 #ifndef SkRecord_DEFINED
9 #define SkRecord_DEFINED 9 #define SkRecord_DEFINED
10 10
(...skipping 28 matching lines...) Expand all
39 fInlineAlloc, sizeof(fInlineAlloc)) {} 39 fInlineAlloc, sizeof(fInlineAlloc)) {}
40 ~SkRecord(); 40 ~SkRecord();
41 41
42 // Returns the number of canvas commands in this SkRecord. 42 // Returns the number of canvas commands in this SkRecord.
43 int count() const { return fCount; } 43 int count() const { return fCount; }
44 44
45 // Visit the i-th canvas command with a functor matching this interface: 45 // Visit the i-th canvas command with a functor matching this interface:
46 // template <typename T> 46 // template <typename T>
47 // R operator()(const T& record) { ... } 47 // R operator()(const T& record) { ... }
48 // This operator() must be defined for at least all SkRecords::*. 48 // This operator() must be defined for at least all SkRecords::*.
49 template <typename R, typename F> 49 template <typename F>
50 R visit(int i, F& f) const { 50 auto visit(int i, F&& f) const -> decltype(f(SkRecords::NoOp())) {
51 SkASSERT(i < this->count()); 51 return fRecords[i].visit(f);
52 return fRecords[i].visit<R>(f);
53 } 52 }
54 53
55 // Mutate the i-th canvas command with a functor matching this interface: 54 // Mutate the i-th canvas command with a functor matching this interface:
56 // template <typename T> 55 // template <typename T>
57 // R operator()(T* record) { ... } 56 // R operator()(T* record) { ... }
58 // This operator() must be defined for at least all SkRecords::*. 57 // This operator() must be defined for at least all SkRecords::*.
59 template <typename R, typename F> 58 template <typename F>
60 R mutate(int i, F& f) { 59 auto mutate(int i, F&& f) -> decltype(f((SkRecords::NoOp*)nullptr)) {
61 SkASSERT(i < this->count()); 60 return fRecords[i].mutate(f);
62 return fRecords[i].mutate<R>(f);
63 } 61 }
64 62
65 // TODO: It'd be nice to infer R from F for visit and mutate.
66
67 // Allocate contiguous space for count Ts, to be freed when the SkRecord is destroyed. 63 // Allocate contiguous space for count Ts, to be freed when the SkRecord is destroyed.
68 // Here T can be any class, not just those from SkRecords. Throws on failur e. 64 // Here T can be any class, not just those from SkRecords. Throws on failur e.
69 template <typename T> 65 template <typename T>
70 T* alloc(size_t count = 1) { 66 T* alloc(size_t count = 1) {
71 return (T*)fAlloc.alloc(sizeof(T) * count); 67 return (T*)fAlloc.alloc(sizeof(T) * count);
72 } 68 }
73 69
74 // Add a new command of type T to the end of this SkRecord. 70 // Add a new command of type T to the end of this SkRecord.
75 // You are expected to placement new an object of type T onto this pointer. 71 // You are expected to placement new an object of type T onto this pointer.
76 template <typename T> 72 template <typename T>
77 T* append() { 73 T* append() {
78 if (fCount == fReserved) { 74 if (fCount == fReserved) {
79 this->grow(); 75 this->grow();
80 } 76 }
81 return fRecords[fCount++].set(this->allocCommand<T>()); 77 return fRecords[fCount++].set(this->allocCommand<T>());
82 } 78 }
83 79
84 // Replace the i-th command with a new command of type T. 80 // Replace the i-th command with a new command of type T.
85 // You are expected to placement new an object of type T onto this pointer. 81 // You are expected to placement new an object of type T onto this pointer.
86 // References to the original command are invalidated. 82 // References to the original command are invalidated.
87 template <typename T> 83 template <typename T>
88 T* replace(int i) { 84 T* replace(int i) {
89 SkASSERT(i < this->count()); 85 SkASSERT(i < this->count());
90 86
91 Destroyer destroyer; 87 Destroyer destroyer;
92 this->mutate<void>(i, destroyer); 88 this->mutate(i, destroyer);
93 89
94 return fRecords[i].set(this->allocCommand<T>()); 90 return fRecords[i].set(this->allocCommand<T>());
95 } 91 }
96 92
97 // Replace the i-th command with a new command of type T. 93 // Replace the i-th command with a new command of type T.
98 // You are expected to placement new an object of type T onto this pointer. 94 // You are expected to placement new an object of type T onto this pointer.
99 // You must show proof that you've already adopted the existing command. 95 // You must show proof that you've already adopted the existing command.
100 template <typename T, typename Existing> 96 template <typename T, typename Existing>
101 T* replace(int i, const SkRecords::Adopted<Existing>& proofOfAdoption) { 97 T* replace(int i, const SkRecords::Adopted<Existing>& proofOfAdoption) {
102 SkASSERT(i < this->count()); 98 SkASSERT(i < this->count());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 T* set(T* ptr) { 157 T* set(T* ptr) {
162 fTypeAndPtr = ((uint64_t)T::kType) << kTypeShift | (uintptr_t)ptr; 158 fTypeAndPtr = ((uint64_t)T::kType) << kTypeShift | (uintptr_t)ptr;
163 SkASSERT(this->ptr() == ptr && this->type() == T::kType); 159 SkASSERT(this->ptr() == ptr && this->type() == T::kType);
164 return ptr; 160 return ptr;
165 } 161 }
166 162
167 SkRecords::Type type() const { return (SkRecords::Type)(fTypeAndPtr >> k TypeShift); } 163 SkRecords::Type type() const { return (SkRecords::Type)(fTypeAndPtr >> k TypeShift); }
168 void* ptr() const { return (void*)(fTypeAndPtr & ((1ull<<kTypeShift)-1)) ; } 164 void* ptr() const { return (void*)(fTypeAndPtr & ((1ull<<kTypeShift)-1)) ; }
169 165
170 // Visit this record with functor F (see public API above). 166 // Visit this record with functor F (see public API above).
171 template <typename R, typename F> 167 template <typename F>
172 R visit(F& f) const { 168 auto visit(F&& f) const -> decltype(f(SkRecords::NoOp())) {
173 #define CASE(T) case SkRecords::T##_Type: return f(*(const SkRecords::T* )this->ptr()); 169 #define CASE(T) case SkRecords::T##_Type: return f(*(const SkRecords::T* )this->ptr());
174 switch(this->type()) { SK_RECORD_TYPES(CASE) } 170 switch(this->type()) { SK_RECORD_TYPES(CASE) }
175 #undef CASE 171 #undef CASE
176 SkDEBUGFAIL("Unreachable"); 172 SkDEBUGFAIL("Unreachable");
177 return R(); 173 return f(SkRecords::NoOp());
178 } 174 }
179 175
180 // Mutate this record with functor F (see public API above). 176 // Mutate this record with functor F (see public API above).
181 template <typename R, typename F> 177 template <typename F>
182 R mutate(F& f) { 178 auto mutate(F&& f) -> decltype(f((SkRecords::NoOp*)nullptr)) {
183 #define CASE(T) case SkRecords::T##_Type: return f((SkRecords::T*)this-> ptr()); 179 #define CASE(T) case SkRecords::T##_Type: return f((SkRecords::T*)this-> ptr());
184 switch(this->type()) { SK_RECORD_TYPES(CASE) } 180 switch(this->type()) { SK_RECORD_TYPES(CASE) }
185 #undef CASE 181 #undef CASE
186 SkDEBUGFAIL("Unreachable"); 182 SkDEBUGFAIL("Unreachable");
187 return R(); 183 return f((SkRecords::NoOp*)nullptr);
188 } 184 }
189 }; 185 };
190 186
191 // fRecords needs to be a data structure that can append fixed length data, and need to 187 // fRecords needs to be a data structure that can append fixed length data, and need to
192 // support efficient random access and forward iteration. (It doesn't need to be contiguous.) 188 // support efficient random access and forward iteration. (It doesn't need to be contiguous.)
193 int fCount, fReserved; 189 int fCount, fReserved;
194 SkAutoSTMalloc<kInlineRecords, Record> fRecords; 190 SkAutoSTMalloc<kInlineRecords, Record> fRecords;
195 191
196 // fAlloc needs to be a data structure which can append variable length data in contiguous 192 // fAlloc needs to be a data structure which can append variable length data in contiguous
197 // chunks, returning a stable handle to that data for later retrieval. 193 // chunks, returning a stable handle to that data for later retrieval.
198 SkVarAlloc fAlloc; 194 SkVarAlloc fAlloc;
199 char fInlineAlloc[1 << kInlineAllocLgBytes]; 195 char fInlineAlloc[1 << kInlineAllocLgBytes];
200 }; 196 };
201 197
202 #endif//SkRecord_DEFINED 198 #endif//SkRecord_DEFINED
OLDNEW
« no previous file with comments | « src/core/SkBigPicture.cpp ('k') | src/core/SkRecord.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698