]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/JSLock.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / JSLock.h
index f4a34eb6eb136fa47af1564064f25d8628df907c..c4339c0fde3e74891cc07161ff3acaa04061cd27 100644 (file)
 
 namespace JSC {
 
-    // To make it safe to use JavaScript on multiple threads, it is
-    // important to lock before doing anything that allocates a
-    // JavaScript data structure or that interacts with shared state
-    // such as the protect count hash table. The simplest way to lock
-    // is to create a local JSLockHolder object in the scope where the lock 
-    // must be held and pass it the context that requires protection. 
-    // The lock is recursive so nesting is ok. The JSLock 
-    // object also acts as a convenience short-hand for running important
-    // initialization routines.
-
-    // To avoid deadlock, sometimes it is necessary to temporarily
-    // release the lock. Since it is recursive you actually have to
-    // release all locks held by your thread. This is safe to do if
-    // you are executing code that doesn't require the lock, and you
-    // reacquire the right number of locks at the end. You can do this
-    // by constructing a locally scoped JSLock::DropAllLocks object. The 
-    // DropAllLocks object takes care to release the JSLock only if your
-    // thread acquired it to begin with.
-
-    class ExecState;
-    class VM;
-
-    // This class is used to protect the initialization of the legacy single 
-    // shared VM.
-    class GlobalJSLock {
-        WTF_MAKE_NONCOPYABLE(GlobalJSLock);
+// To make it safe to use JavaScript on multiple threads, it is
+// important to lock before doing anything that allocates a
+// JavaScript data structure or that interacts with shared state
+// such as the protect count hash table. The simplest way to lock
+// is to create a local JSLockHolder object in the scope where the lock 
+// must be held and pass it the context that requires protection. 
+// The lock is recursive so nesting is ok. The JSLock 
+// object also acts as a convenience short-hand for running important
+// initialization routines.
+
+// To avoid deadlock, sometimes it is necessary to temporarily
+// release the lock. Since it is recursive you actually have to
+// release all locks held by your thread. This is safe to do if
+// you are executing code that doesn't require the lock, and you
+// reacquire the right number of locks at the end. You can do this
+// by constructing a locally scoped JSLock::DropAllLocks object. The 
+// DropAllLocks object takes care to release the JSLock only if your
+// thread acquired it to begin with.
+
+class ExecState;
+class VM;
+
+// This class is used to protect the initialization of the legacy single 
+// shared VM.
+class GlobalJSLock {
+    WTF_MAKE_NONCOPYABLE(GlobalJSLock);
+public:
+    JS_EXPORT_PRIVATE GlobalJSLock();
+    JS_EXPORT_PRIVATE ~GlobalJSLock();
+
+    static void initialize();
+private:
+    static std::mutex* s_sharedInstanceMutex;
+};
+
+class JSLockHolder {
+public:
+    JS_EXPORT_PRIVATE JSLockHolder(VM*);
+    JS_EXPORT_PRIVATE JSLockHolder(VM&);
+    JS_EXPORT_PRIVATE JSLockHolder(ExecState*);
+
+    JS_EXPORT_PRIVATE ~JSLockHolder();
+private:
+    void init();
+
+    RefPtr<VM> m_vm;
+};
+
+class JSLock : public ThreadSafeRefCounted<JSLock> {
+    WTF_MAKE_NONCOPYABLE(JSLock);
+public:
+    JSLock(VM*);
+    JS_EXPORT_PRIVATE ~JSLock();
+
+    JS_EXPORT_PRIVATE void lock();
+    JS_EXPORT_PRIVATE void unlock();
+
+    static void lock(ExecState*);
+    static void unlock(ExecState*);
+    static void lock(VM&);
+    static void unlock(VM&);
+
+    VM* vm() { return m_vm; }
+
+    bool hasExclusiveThread() const { return m_hasExclusiveThread; }
+    std::thread::id exclusiveThread() const
+    {
+        ASSERT(m_hasExclusiveThread);
+        return m_ownerThreadID;
+    }
+    JS_EXPORT_PRIVATE void setExclusiveThread(std::thread::id);
+    JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock();
+
+    void willDestroyVM(VM*);
+
+    class DropAllLocks {
+        WTF_MAKE_NONCOPYABLE(DropAllLocks);
     public:
-        JS_EXPORT_PRIVATE GlobalJSLock();
-        JS_EXPORT_PRIVATE ~GlobalJSLock();
+        JS_EXPORT_PRIVATE DropAllLocks(ExecState*);
+        JS_EXPORT_PRIVATE DropAllLocks(VM*);
+        JS_EXPORT_PRIVATE DropAllLocks(VM&);
+        JS_EXPORT_PRIVATE ~DropAllLocks();
 
-        static void initialize();
-    private:
-        static std::mutex* s_sharedInstanceMutex;
-    };
+        void setDropDepth(unsigned depth) { m_dropDepth = depth; }
+        unsigned dropDepth() const { return m_dropDepth; }
 
-    class JSLockHolder {
-    public:
-        JS_EXPORT_PRIVATE JSLockHolder(VM*);
-        JS_EXPORT_PRIVATE JSLockHolder(VM&);
-        JS_EXPORT_PRIVATE JSLockHolder(ExecState*);
-
-        JS_EXPORT_PRIVATE ~JSLockHolder();
     private:
-        void init();
-
+        intptr_t m_droppedLockCount;
         RefPtr<VM> m_vm;
+        unsigned m_dropDepth;
     };
 
-    class JSLock : public ThreadSafeRefCounted<JSLock> {
-        WTF_MAKE_NONCOPYABLE(JSLock);
-    public:
-        JSLock(VM*);
-        JS_EXPORT_PRIVATE ~JSLock();
-
-        JS_EXPORT_PRIVATE void lock();
-        JS_EXPORT_PRIVATE void unlock();
-
-        static void lock(ExecState*);
-        static void unlock(ExecState*);
-        static void lock(VM&);
-        static void unlock(VM&);
-
-        VM* vm() { return m_vm; }
-
-        bool hasExclusiveThread() const { return m_hasExclusiveThread; }
-        std::thread::id exclusiveThread() const
-        {
-            ASSERT(m_hasExclusiveThread);
-            return m_ownerThreadID;
-        }
-        JS_EXPORT_PRIVATE void setExclusiveThread(std::thread::id);
-        JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock();
-
-        void willDestroyVM(VM*);
-
-        class DropAllLocks {
-            WTF_MAKE_NONCOPYABLE(DropAllLocks);
-        public:
-            JS_EXPORT_PRIVATE DropAllLocks(ExecState*);
-            JS_EXPORT_PRIVATE DropAllLocks(VM*);
-            JS_EXPORT_PRIVATE DropAllLocks(VM&);
-            JS_EXPORT_PRIVATE ~DropAllLocks();
-            
-            void setDropDepth(unsigned depth) { m_dropDepth = depth; }
-            unsigned dropDepth() const { return m_dropDepth; }
-
-        private:
-            intptr_t m_droppedLockCount;
-            RefPtr<VM> m_vm;
-            unsigned m_dropDepth;
-        };
+private:
+    void lock(intptr_t lockCount);
+    void unlock(intptr_t unlockCount);
 
-    private:
-        void lock(intptr_t lockCount);
-        void unlock(intptr_t unlockCount);
-
-        void didAcquireLock();
-        void willReleaseLock();
-
-        unsigned dropAllLocks(DropAllLocks*);
-        void grabAllLocks(DropAllLocks*, unsigned lockCount);
-
-        std::mutex m_lock;
-        std::thread::id m_ownerThreadID;
-        intptr_t m_lockCount;
-        unsigned m_lockDropDepth;
-        bool m_hasExclusiveThread;
-        VM* m_vm;
-        AtomicStringTable* m_entryAtomicStringTable; 
-    };
+    void didAcquireLock();
+    void willReleaseLock();
+
+    unsigned dropAllLocks(DropAllLocks*);
+    void grabAllLocks(DropAllLocks*, unsigned lockCount);
+
+    std::mutex m_lock;
+    std::thread::id m_ownerThreadID;
+    intptr_t m_lockCount;
+    unsigned m_lockDropDepth;
+    bool m_hasExclusiveThread;
+    VM* m_vm;
+    AtomicStringTable* m_entryAtomicStringTable; 
+};
 
 } // namespace