| Index: src/core/SkFunction.h
|
| diff --git a/src/core/SkFunction.h b/src/core/SkFunction.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9ec421e2a6789c69db1d1691091dd80fbfe8151e
|
| --- /dev/null
|
| +++ b/src/core/SkFunction.h
|
| @@ -0,0 +1,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
|
|
|