1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkFunction_DEFINED
#define SkFunction_DEFINED
// TODO: document
#include "SkTypes.h"
template <typename> class SkFunction;
template <typename R, typename... Args>
class SkFunction<R(Args...)> : SkNoncopyable {
public:
explicit SkFunction(R (*fn)(Args...)) : fVTable(GetFunctionPointerVTable()) {
// We've been passed a function pointer. We'll just store it.
fFunction = reinterpret_cast<void*>(fn);
}
template <typename Fn>
explicit SkFunction(Fn fn) : fVTable(GetVTable<Fn>()) {
// We've got a functor. The basic thing we can always do is copy it onto the heap.
fFunction = SkNEW_ARGS(Fn, (fn));
}
~SkFunction() { fVTable.fDelete(fFunction); }
R operator()(Args... args) { return fVTable.fCall(fFunction, args...); }
private:
struct VTable {
R (*fCall)(void*, Args...);
void (*fDelete)(void*);
};
static const VTable& GetFunctionPointerVTable() {
static const VTable vtable = {
[](void* fn, Args... args) { return reinterpret_cast<R(*)(Args...)>(fn)(args...); },
[](void*) { /* Don't delete function pointers. */ },
};
return vtable;
}
template <typename Fn>
static const VTable& GetVTable() {
static const VTable vtable = {
[](void* fn, Args... args) { return (*static_cast<Fn*>(fn))(args...); },
[](void* fn) { SkDELETE(static_cast<Fn*>(fn)); },
};
return vtable;
}
void* fFunction; // Either a function pointer, or a pointer to a functor.
const VTable& fVTable; // How to call, delete (and one day copy, move) fFunction.
};
// TODO:
// - is it worth moving fCall out of the VTable into SkFunction itself to avoid the indirection?
// - should constructors be implicit?
// - make SkFunction copyable
// - emulate std::forward for moveable functors (e.g. lambdas)
// - forward args too?
// - implement small-object optimization to store functors inline
#endif//SkFunction_DEFINED
|