Index: Source/core/dom/LockManager.cpp |
diff --git a/Source/core/dom/LockManager.cpp b/Source/core/dom/LockManager.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ef1b30bb96a76bd11422d820ce77b51db1f7f19c |
--- /dev/null |
+++ b/Source/core/dom/LockManager.cpp |
@@ -0,0 +1,164 @@ |
+/* |
+ * Copyright (C) 2014 Google Inc. All Rights Reserved. |
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions |
+ * are met: |
+ * 1. Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * 2. Redistributions in binary form must reproduce the above copyright |
+ * notice, this list of conditions and the following disclaimer in the |
+ * documentation and/or other materials provided with the distribution. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ * |
+ */ |
+ |
+#include "config.h" |
+#include "core/dom/LockManager.h" |
+ |
+#include "core/dom/ExecutionContext.h" |
+ |
+namespace WebCore { |
+ |
+static inline uint32_t murmurHash3Finalize(uint32_t h) |
+{ |
+ h ^= h >> 16; |
+ h *= 0x85ebca6b; |
+ h ^= h >> 13; |
+ h *= 0xc2b2ae35; |
+ h ^= h >> 16; |
+ return h; |
+} |
+ |
+static inline void getIndexes(uint32_t uid, uint32_t *shard, uint32_t *lock) |
+{ |
+ uint32_t hash = murmurHash3Finalize(uid); |
+ *shard = hash & SHARD_MASK; |
+ *lock = hash >> SHARD_BITS; |
+} |
+ |
+class LockInfo { |
+public: |
+ LockInfo(); |
+ bool locked; |
+ ThreadCondition cond; |
+ uint32_t holdCount; |
+}; |
+ |
+LockInfo::LockInfo() |
+ : locked(false) |
+ , holdCount(0) |
+{ |
+} |
+ |
+LockShard::~LockShard() |
+{ |
+ // printf("destroying shard %p\n", this); |
+ LockHashMap::iterator iter; |
+ for (iter = locks.begin(); iter != locks.end(); ++iter) { |
+ delete iter->value; |
+ } |
+ locks.clear(); |
+} |
+ |
+LockInfo* LockShard::get(uint32_t uid) |
+{ |
+ LockHashMap::iterator iter = locks.find(uid); |
+ if (iter != locks.end()) { |
+ return iter->value; |
+ } |
+ LockInfo* info = new LockInfo(); |
+ locks.add(uid, info); |
+ return info; |
+} |
+ |
+void LockManagerImpl::lock(uint32_t uid) |
+{ |
+ uint32_t shardID; |
+ uint32_t lock; |
+ getIndexes(uid, &shardID, &lock); |
+ LockShard& shard = shards[shardID]; |
+ shard.mutex.lock(); |
+ LockInfo* info = shard.get(lock); |
+ // printf("enter %u %u %u\n", uid, shardID, lock); |
+ info->holdCount += 1; |
+ if (info->holdCount != 1) { |
+ info->cond.wait(shard.mutex); |
+ } |
+ // printf("lock %u %u %u\n", uid, shardID, lock); |
+ shard.mutex.unlock(); |
+} |
+ |
+void LockManagerImpl::unlock(uint32_t uid) |
+{ |
+ uint32_t shardID; |
+ uint32_t lock; |
+ getIndexes(uid, &shardID, &lock); |
+ LockShard& shard = shards[shardID]; |
+ shard.mutex.lock(); |
+ LockInfo* info = shard.get(lock); |
+ info->holdCount -= 1; |
+ if (info->holdCount) { |
+ info->cond.signal(); |
+ } |
+ // printf("unlock %u %u %u\n", uid, shardID, lock); |
+ shard.mutex.unlock(); |
+} |
+ |
+// Store the impl in a singleton to avoid the need to transfer the lock manager. |
+// This is an awful hack to speed up prototyping. |
+class LockManagerHack { |
+public: |
+ ~LockManagerHack() |
+ { |
+ } |
+ PassRefPtr<LockManagerImpl> get() |
+ { |
+ MutexLocker lock(m); |
+ if (!impl) { |
+ impl = adoptRef(new LockManagerImpl()); |
+ } |
+ return impl; |
+ } |
+private: |
+ Mutex m; |
+ RefPtr<LockManagerImpl> impl; |
+}; |
+ |
+#pragma clang diagnostic push |
+#pragma clang diagnostic ignored "-Wglobal-constructors" |
+#pragma clang diagnostic ignored "-Wexit-time-destructors" |
+static LockManagerHack hack; |
+#pragma clang diagnostic pop |
+ |
+LockManager::LockManager(ExecutionContext*) |
+: impl(hack.get()) |
+{ |
+} |
+ |
+void LockManager::lock(unsigned long uid) |
+{ |
+ impl->lock(uid); |
+} |
+ |
+void LockManager::unlock(unsigned long uid) |
+{ |
+ impl->unlock(uid); |
+} |
+ |
+void LockManager::nop() |
+{ |
+} |
+ |
+} // namespace WebCore |