aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core
diff options
context:
space:
mode:
authorGravatar digit@google.com <digit@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-26 21:26:40 +0000
committerGravatar digit@google.com <digit@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-26 21:26:40 +0000
commit1771cbf43d9a1334e3d870c635b4215bb888dd98 (patch)
treeb32203ccd81d3747e2cc36d5e71ee7cadcff03fa /include/core
parent72b55be3f3448287e8ff6fe83633edadfb60f59a (diff)
posix: Avoid static initializers in static/global mutexes
This patch removes static initializers related to static and global mutexes from the final library's machine code when building on a pthread-capable system. We use PTHREAD_MUTEX_INITIALIZER to perform POD-style initialization. You need a line like the following to declare a global mutex with it: SkBaseMutex gMutex = { PTHREAD_MUTEX_INITIALIZER }; We introduce the SK_DECLARE_STATIC_MUTEX and SK_DECLARE_GLOBAL_MUTEX macros to be able to declare static/global mutexes in the source tree uniformly. SkMutex is now defined as a sub-class of SkBaseMutex, with standard construction/destruction semantics. This is useful if the mutex object is a member of another C++ class, or allocated dynamically. We also modify a few places to refer to SkBaseMutex instead of a SkMutex, where it makes sense. Generally speaking, client code should hold and use pointers to SkBaseMutex whenever they can now. We defined a new built-time macro named SK_USE_POSIX_THREADS to indicate that we're using a pthread-based SkThread.h interface. The macro will also be used in future patches to implement other helper thread synchronization classes. Finally, we inline the acquire() and release() functions in the case of Posix to improve performance a bit. Running: 'bench -repeat 10 -match mutex' on an Android device or a 2.4GHz Xeon Linux desktop shows the following improvements: Before After Galaxy Nexus 1.64 1.45 Nexus S 1.47 1.16 Xoom 1.86 1.66 Xeon 0.36 0.31 This removes 5 static mutex initializers from the library Review URL: https://codereview.appspot.com/5501066 git-svn-id: http://skia.googlecode.com/svn/trunk@3091 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'include/core')
-rw-r--r--include/core/SkPixelRef.h8
-rw-r--r--include/core/SkThread.h4
-rw-r--r--include/core/SkThread_platform.h47
3 files changed, 51 insertions, 8 deletions
diff --git a/include/core/SkPixelRef.h b/include/core/SkPixelRef.h
index e247479ad5..3f0784433e 100644
--- a/include/core/SkPixelRef.h
+++ b/include/core/SkPixelRef.h
@@ -52,7 +52,7 @@ class SkGpuTexture;
*/
class SkPixelRef : public SkRefCnt {
public:
- explicit SkPixelRef(SkMutex* mutex = NULL);
+ explicit SkPixelRef(SkBaseMutex* mutex = NULL);
/** Return the pixel memory returned from lockPixels, or null if the
lockCount is 0.
@@ -201,16 +201,16 @@ protected:
/** Return the mutex associated with this pixelref. This value is assigned
in the constructor, and cannot change during the lifetime of the object.
*/
- SkMutex* mutex() const { return fMutex; }
+ SkBaseMutex* mutex() const { return fMutex; }
- SkPixelRef(SkFlattenableReadBuffer&, SkMutex*);
+ SkPixelRef(SkFlattenableReadBuffer&, SkBaseMutex*);
private:
#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
static void InitializeFlattenables();
#endif
- SkMutex* fMutex; // must remain in scope for the life of this object
+ SkBaseMutex* fMutex; // must remain in scope for the life of this object
void* fPixels;
SkColorTable* fColorTable; // we do not track ownership, subclass does
int fLockCount;
diff --git a/include/core/SkThread.h b/include/core/SkThread.h
index 5f2da4a006..1495a16fa9 100644
--- a/include/core/SkThread.h
+++ b/include/core/SkThread.h
@@ -31,7 +31,7 @@ public:
class SkAutoMutexAcquire : SkNoncopyable {
public:
- explicit SkAutoMutexAcquire(SkMutex& mutex) : fMutex(&mutex)
+ explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex)
{
SkASSERT(fMutex != NULL);
mutex.acquire();
@@ -55,7 +55,7 @@ public:
}
private:
- SkMutex* fMutex;
+ SkBaseMutex* fMutex;
};
#endif
diff --git a/include/core/SkThread_platform.h b/include/core/SkThread_platform.h
index cbb4891c1a..94a4a1edeb 100644
--- a/include/core/SkThread_platform.h
+++ b/include/core/SkThread_platform.h
@@ -78,7 +78,44 @@ SK_API int32_t sk_atomic_inc(int32_t* addr);
*/
SK_API int32_t sk_atomic_dec(int32_t* addr);
-class SkMutex {
+#endif
+
+#ifdef SK_USE_POSIX_THREADS
+
+#include <pthread.h>
+
+// A SkBaseMutex is a POD structure that can be directly initialized
+// at declaration time with SK_DECLARE_STATIC/GLOBAL_MUTEX. This avoids the
+// generation of a static initializer in the final machine code (and
+// a corresponding static finalizer).
+//
+struct SkBaseMutex {
+ void acquire() { pthread_mutex_lock(&fMutex); }
+ void release() { pthread_mutex_unlock(&fMutex); }
+ pthread_mutex_t fMutex;
+};
+
+// Using POD-style initialization prevents the generation of a static initializer
+// and keeps the acquire() implementation small and fast.
+#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER }
+
+// Special case used when the static mutex must be available globally.
+#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = { PTHREAD_MUTEX_INITIALIZER }
+
+// A normal mutex that requires to be initialized through normal C++ construction,
+// i.e. when it's a member of another class, or allocated on the heap.
+class SkMutex : public SkBaseMutex, SkNoncopyable {
+public:
+ SkMutex();
+ ~SkMutex();
+};
+
+#else // !SK_USE_POSIX_THREADS
+
+// In the generic case, SkBaseMutex and SkMutex are the same thing, and we
+// can't easily get rid of static initializers.
+//
+class SkMutex : SkNoncopyable {
public:
SkMutex();
~SkMutex();
@@ -94,6 +131,12 @@ private:
uint32_t fStorage[kStorageIntCount];
};
-#endif
+typedef SkMutex SkBaseMutex;
+
+#define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name
+#define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name
+
+#endif // !SK_USE_POSIX_THREADS
+
#endif