Index: include/core/SkOnce.h |
diff --git a/include/core/SkOnce.h b/include/core/SkOnce.h |
index 9c4ccd49d06ab403b1cebbc0f77e25cec4cca1c3..9663ef13bfc2af06b26484d619fccfef8c836473 100644 |
--- a/include/core/SkOnce.h |
+++ b/include/core/SkOnce.h |
@@ -25,6 +25,8 @@ |
// } |
// |
// OnceTest.cpp also should serve as a few other simple examples. |
+// |
+// You may optionally pass SkOnce a second function to be called at exit for cleanup. |
#include "SkThread.h" |
#include "SkTypes.h" |
@@ -35,7 +37,7 @@ |
struct SkOnceFlag; // If manually created, initialize with SkOnceFlag once = SK_ONCE_INIT |
template <typename Func, typename Arg> |
-inline void SkOnce(SkOnceFlag* once, Func f, Arg arg); |
+inline void SkOnce(SkOnceFlag* once, Func f, Arg arg, void(*atExit)() = NULL); |
// ---------------------- Implementation details below here. ----------------------------- |
@@ -92,10 +94,13 @@ inline static void acquire_barrier() { |
// This should be rarely called, so we separate it from SkOnce and don't mark it as inline. |
// (We don't mind if this is an actual function call, but odds are it'll be inlined anyway.) |
template <typename Func, typename Arg> |
-static void sk_once_slow(SkOnceFlag* once, Func f, Arg arg) { |
+static void sk_once_slow(SkOnceFlag* once, Func f, Arg arg, void (*atExit)()) { |
const SkAutoSpinlock lock(&once->lock); |
if (!once->done) { |
f(arg); |
+ if (atExit != NULL) { |
+ atexit(atExit); |
+ } |
// Also known as a store-store/load-store barrier, this makes sure that the writes |
// done before here---in particular, those done by calling f(arg)---are observable |
// before the writes after the line, *done = true. |
@@ -127,10 +132,10 @@ void AnnotateBenignRace(const char* file, int line, const volatile void* mem, co |
// This is our fast path, called all the time. We do really want it to be inlined. |
template <typename Func, typename Arg> |
-inline void SkOnce(SkOnceFlag* once, Func f, Arg arg) { |
+inline void SkOnce(SkOnceFlag* once, Func f, Arg arg, void(*atExit)()) { |
SK_ANNOTATE_BENIGN_RACE(&(once->done), "Don't worry TSAN, we're sure this is safe."); |
if (!once->done) { |
- sk_once_slow(once, f, arg); |
+ sk_once_slow(once, f, arg, atExit); |
} |
// Also known as a load-load/load-store barrier, this acquire barrier makes |
// sure that anything we read from memory---in particular, memory written by |