Chromium Code Reviews| Index: test/cctest/test-lockers.cc |
| diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3499f7134338f37fac6e09152728292994fa5e77 |
| --- /dev/null |
| +++ b/test/cctest/test-lockers.cc |
| @@ -0,0 +1,602 @@ |
| +// Copyright 2007-2009 the V8 project authors. All rights reserved. |
|
Vitaly Repeshko
2011/04/15 00:29:39
2011
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| +// Redistribution and use in source and binary forms, with or without |
| +// modification, are permitted provided that the following conditions are |
| +// met: |
| +// |
| +// * Redistributions of source code must retain the above copyright |
| +// notice, this list of conditions and the following disclaimer. |
| +// * 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. |
| +// * Neither the name of Google Inc. nor the names of its |
| +// contributors may be used to endorse or promote products derived |
| +// from this software without specific prior written permission. |
| +// |
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| +// "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 THE COPYRIGHT |
| +// OWNER 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 <limits.h> |
| +#include <vector> |
| + |
| +#include "v8.h" |
| + |
| +#include "api.h" |
| +#include "isolate.h" |
| +#include "compilation-cache.h" |
| +#include "execution.h" |
| +#include "snapshot.h" |
| +#include "platform.h" |
| +#include "utils.h" |
| +#include "cctest.h" |
| +#include "parser.h" |
| +#include "unicode-inl.h" |
| + |
| +using ::v8::AccessorInfo; |
| +using ::v8::Context; |
| +using ::v8::Extension; |
| +using ::v8::Function; |
| +using ::v8::HandleScope; |
| +using ::v8::Local; |
| +using ::v8::Object; |
| +using ::v8::ObjectTemplate; |
| +using ::v8::Persistent; |
| +using ::v8::Script; |
| +using ::v8::String; |
| +using ::v8::Value; |
| +using ::v8::V8; |
| + |
| +namespace i = ::i; |
| + |
| + |
| + |
| + |
| +// Migrating an isolate |
| +class KangarooThread : public v8::internal::Thread { |
| + public: |
| + explicit KangarooThread(v8::Isolate* isolate, |
|
Vitaly Repeshko
2011/04/15 00:29:39
nit: explicit not required.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + v8::Handle<v8::Context> context, int value) |
|
Vitaly Repeshko
2011/04/15 00:29:39
nit: Weird indentation.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + : Thread(NULL, "KangarooThread1"), |
|
Vitaly Repeshko
2011/04/15 00:29:39
Why 1? There doesn't seem to be a second one.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + isolate_(isolate), context_(context), value_(value) { |
| + } |
| + |
| + void Run() { |
| + { |
| + v8::Locker locker(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + CHECK_EQ(isolate_, v8::internal::Isolate::Current()); |
| + v8::HandleScope scope; |
| + context_->Enter(); |
|
Vitaly Repeshko
2011/04/15 00:29:39
Please use Context::Scope where possible.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + Local<Value> v = CompileRun("getValue()"); |
| + CHECK(v->IsNumber()); |
| + CHECK_EQ(30, static_cast<int>(v->NumberValue())); |
| + context_->Exit(); |
| + } |
| + { |
| + v8::Locker locker(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + context_->Enter(); |
| + v8::HandleScope scope; |
| + Local<Value> v = CompileRun("getValue()"); |
| + CHECK(v->IsNumber()); |
| + CHECK_EQ(30, static_cast<int>(v->NumberValue())); |
| + context_->Exit(); |
| + } |
| + isolate_->Dispose(); |
| + } |
| + |
| + private: |
| + v8::Isolate* isolate_; |
| + Persistent<v8::Context> context_; |
| + int value_; |
| +}; |
| + |
| + |
| +TEST(KangarooIsolates) { |
|
Vitaly Repeshko
2011/04/15 00:29:39
Please describe what a test does for non-trivial t
|
| + v8::Isolate* isolate = v8::Isolate::New(); |
| + Persistent<v8::Context> context; |
| + { |
| + v8::Locker locker_(isolate); |
|
Vitaly Repeshko
2011/04/15 00:29:39
nit: Why _ ?
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + v8::Isolate::Scope isolate_scope(isolate); |
| + v8::HandleScope handle_scope; |
| + context = v8::Context::New(); |
| + context->Enter(); |
| + CHECK_EQ(isolate, v8::internal::Isolate::Current()); |
| + CompileRun("function getValue() { return 30; }"); |
|
Vitaly Repeshko
2011/04/15 00:29:39
It'd be useful for this script to have some state,
Dmitry Lomov
2011/04/19 01:50:47
It has a state of sorts - note that KangarooThread
|
| + context->Exit(); |
| + } |
| + KangarooThread thread1(isolate, context, 1); |
| + thread1.Start(); |
| + thread1.Join(); |
| +} |
| + |
| +static void CalcFibAndCheck() { |
| + Local<Value> v = CompileRun("function fib(n) {" |
| + " if (n <= 2) return 1;" |
| + " return fib(n-1) + fib(n-2);" |
| + "}" |
| + "fib(10)"); |
| + CHECK(v->IsNumber()); |
| + CHECK_EQ(55, static_cast<int>(v->NumberValue())); |
| +} |
| + |
| +class JoinableThread : public i::Thread { |
|
Vitaly Repeshko
2011/04/15 00:29:39
To make this a bit more readable make JoinableThre
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + public: |
| + explicit JoinableThread(i::Isolate* isolate, const char* name) |
| + : Thread(isolate, name), |
| + semaphore_(NULL) { |
| + } |
| + |
| + void StartWithSignal(i::Semaphore* semaphore) { |
| + semaphore_ = semaphore; |
| + Start(); |
| + } |
| + |
| + void Run() { |
|
Vitaly Repeshko
2011/04/15 00:29:39
nit: Keep "virtual" when overriding.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + DoRun(); |
| + if (semaphore_ != NULL) |
| + semaphore_->Signal(); |
| + } |
| + virtual void DoRun() = 0; |
| + private: |
| + i::Semaphore* semaphore_; |
| +}; |
| + |
| + |
| +class IsolateLockingThreadWithLocalContext : public JoinableThread { |
| + public: |
| + explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate) |
| + : JoinableThread(NULL, "IsolateLockingThread"), |
| + isolate_(isolate) { |
| + } |
| + |
| + void DoRun() { |
| + v8::Locker locker(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + v8::HandleScope handle_scope; |
| + LocalContext local_context; |
| + CHECK_EQ(isolate_, v8::internal::Isolate::Current()); |
| + CalcFibAndCheck(); |
| + } |
| + private: |
| + v8::Isolate* isolate_; |
| +}; |
| + |
| +static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) { |
| + i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
| + for (int i = 0; i < threads.length(); i++) { |
| + threads[i]->StartWithSignal(semaphore); |
| + } |
| + for (int i = 0; i < threads.length(); i++) { |
| + semaphore->Wait(); |
| + } |
| + for (int i = 0; i < threads.length(); i++) { |
| + delete threads[i]; |
| + } |
| + delete semaphore; |
| +} |
| + |
| +TEST(IsolateLockingStress) { |
| + const int kNThreads = 100; |
| + i::List<JoinableThread*> threads(kNThreads); |
| + v8::Isolate* isolate = v8::Isolate::New(); |
| + for (int i = 0; i < kNThreads; i++) { |
| + threads.Add(new IsolateLockingThreadWithLocalContext(isolate)); |
| + } |
| + StartJoinAndDeleteThreads(threads); |
| + isolate->Dispose(); |
| +} |
| + |
| +class IsolateNonlockingThread : public JoinableThread { |
| + public: |
| + explicit IsolateNonlockingThread() |
| + : JoinableThread(NULL, "IsolateNonlockingThread") { |
| + } |
| + |
| + void DoRun() { |
| + v8::Isolate* isolate = v8::Isolate::New(); |
| + { |
| + v8::Isolate::Scope isolate_scope(isolate); |
| + v8::HandleScope handle_scope; |
| + v8::Handle<v8::Context> context = v8::Context::New(); |
| + context->Enter(); |
| + CHECK_EQ(isolate, v8::internal::Isolate::Current()); |
| + CalcFibAndCheck(); |
| + context->Exit(); |
|
Vitaly Repeshko
2011/04/15 00:29:39
nit: Fix indentation.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + } |
| + isolate->Dispose(); |
| + } |
| + private: |
| +}; |
| + |
| +TEST(MultithreadedParallelIsolates) { |
| + const int kNThreads = 50; |
| + i::List<JoinableThread*> threads(kNThreads); |
| + for (int i = 0; i < kNThreads; i++) { |
| + threads.Add(new IsolateNonlockingThread()); |
| + } |
| + StartJoinAndDeleteThreads(threads); |
| +} |
| + |
| + |
| +class IsolateLockingTwiceThread : public JoinableThread { |
|
Vitaly Repeshko
2011/04/15 00:29:39
LockingTwice -> NestedLocking
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + public: |
| + explicit IsolateLockingTwiceThread(v8::Isolate* isolate) |
| + : JoinableThread(NULL, "IsolateLockingTwice"), isolate_(isolate) { |
| + } |
| + void DoRun() { |
| + v8::Locker lock(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + v8::HandleScope handle_scope; |
| + LocalContext local_context; |
| + { |
| + v8::Locker another_lock(isolate_); |
| + CalcFibAndCheck(); |
| + } |
| + { |
| + v8::Locker another_lock(isolate_); |
| + CalcFibAndCheck(); |
| + } |
| + } |
| + private: |
| + v8::Isolate* isolate_; |
| +}; |
| + |
| +TEST(IsolateLockingTwice) { |
| + const int kNThreads = 100; |
| + v8::Isolate* isolate = v8::Isolate::New(); |
| + i::List<JoinableThread*> threads(kNThreads); |
| + for (int i = 0; i < kNThreads; i++) { |
| + threads.Add(new IsolateLockingTwiceThread(isolate)); |
| + } |
| + StartJoinAndDeleteThreads(threads); |
| +} |
| + |
| +class LockIsolateAndCalculateFibThread : public JoinableThread { |
|
Vitaly Repeshko
2011/04/15 00:29:39
Isn't this the same as IsolateLockingThreadWithLoc
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + public: |
| + explicit LockIsolateAndCalculateFibThread(v8::Isolate* isolate) |
| + : JoinableThread(NULL, "LockIsolateAndCalculateFibThread"), |
| + isolate_(isolate) { |
| + } |
| + |
| + void DoRun() { |
| + v8::Locker lock(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + LocalContext local_context; |
| + HandleScope handle_scope; |
| + CalcFibAndCheck(); |
| + } |
| + private: |
| + v8::Isolate* isolate_; |
| +}; |
| + |
| +class SeparateIsolatesLocksNonexclusiveThreadA : public JoinableThread { |
| + public: |
| + explicit SeparateIsolatesLocksNonexclusiveThreadA(v8::Isolate* isolate1, |
|
Vitaly Repeshko
2011/04/15 00:29:39
nit: explicit not required.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + v8::Isolate* isolate2) |
| + : JoinableThread(NULL, "ASeparateIsolatesLocksNonexclusiveThreadA"), |
|
Vitaly Repeshko
2011/04/15 00:29:39
Why "A"? There doesn't seem to be a "B" variant of
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + isolate1_(isolate1), isolate2_(isolate2) { |
| + } |
| + |
| + void DoRun() { |
| + v8::Locker lock(isolate1_); |
| + v8::Isolate::Scope isolate_scope(isolate1_); |
| + v8::HandleScope handle_scope; |
| + LocalContext local_context; |
| + |
| + LockIsolateAndCalculateFibThread threadB(isolate2_); |
| + i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
| + threadB.StartWithSignal(semaphore); |
| + CalcFibAndCheck(); |
| + semaphore->Wait(); |
| + delete semaphore; |
| + } |
| + private: |
| + v8::Isolate* isolate1_; |
| + v8::Isolate* isolate2_; |
| +}; |
| + |
| +TEST(SeparateIsolatesLocksNonexclusive) { |
| + const int kNThreads = 100; |
| + v8::Isolate* isolate1 = v8::Isolate::New(); |
| + v8::Isolate* isolate2 = v8::Isolate::New(); |
| + i::List<JoinableThread*> threads(kNThreads); |
| + for (int i = 0; i < kNThreads; i++) { |
| + threads.Add(new SeparateIsolatesLocksNonexclusiveThreadA(isolate1, |
| + isolate2)); |
| + } |
| + StartJoinAndDeleteThreads(threads); |
| + isolate2->Dispose(); |
| + isolate1->Dispose(); |
| +} |
| + |
| +class LockIsolateAndCalculateFibSharedContextThread : public JoinableThread { |
| + public: |
| + explicit LockIsolateAndCalculateFibSharedContextThread( |
| + v8::Isolate* isolate, v8::Handle<v8::Context> context) |
| + : JoinableThread(NULL, "LockIsolateAndCalculateFibThread"), |
| + isolate_(isolate), |
| + context_(context) { |
| + } |
| + |
| + void DoRun() { |
| + v8::Locker lock(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + HandleScope handle_scope; |
| + context_->Enter(); |
| + CalcFibAndCheck(); |
| + context_->Exit(); |
| + } |
| + private: |
| + v8::Isolate* isolate_; |
| + Persistent<v8::Context> context_; |
| +}; |
| + |
| +class LockerUnlockerThread : public JoinableThread { |
| + public: |
| + explicit LockerUnlockerThread(v8::Isolate* isolate) |
| + : JoinableThread(NULL, "LockerUnlockerThread"), |
| + isolate_(isolate) { |
| + } |
| + |
| + void DoRun() { |
| + v8::Locker lock(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + v8::HandleScope handle_scope; |
| + v8::Handle<v8::Context> context = v8::Context::New(); |
| + context->Enter(); |
| + CalcFibAndCheck(); |
| + { |
| + context->Exit(); |
|
Vitaly Repeshko
2011/04/15 00:29:39
Do we have to exit the context here?
Dmitry Lomov
2011/04/19 01:50:47
Yes because we exit the isolate - in the next line
|
| + isolate_->Exit(); |
| + v8::Unlocker unlocker(isolate_); |
|
Vitaly Repeshko
2011/04/15 00:29:39
Hmm, do we really want to be able to unlock some a
Dmitry Lomov
2011/04/19 01:50:47
Here is what I think on the subject:
1. I do not h
|
| + LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context); |
| + i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
| + thread.StartWithSignal(semaphore); |
| + semaphore->Wait(); |
| + delete semaphore; |
| + } |
| + isolate_->Enter(); |
| + context->Enter(); |
| + CalcFibAndCheck(); |
|
Vitaly Repeshko
2011/04/15 00:29:39
context->Exit()?
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + } |
| + private: |
| + v8::Isolate* isolate_; |
| +}; |
| + |
| +TEST(LockerUnlocker) { |
| + const int kNThreads = 100; |
| + i::List<JoinableThread*> threads(kNThreads); |
| + v8::Isolate* isolate = v8::Isolate::New(); |
| + for (int i = 0; i < kNThreads; i++) { |
| + threads.Add(new LockerUnlockerThread(isolate)); |
| + } |
| + StartJoinAndDeleteThreads(threads); |
| + isolate->Dispose(); |
| +} |
| + |
| +class LockTwiceAndUnlockThread : public JoinableThread { |
| + public: |
| + explicit LockTwiceAndUnlockThread(v8::Isolate* isolate) |
| + : JoinableThread(NULL, "LockTwiceAndUnlockThread"), |
| + isolate_(isolate) { |
| + } |
| + |
| + void DoRun() { |
| + v8::Locker lock(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + v8::HandleScope handle_scope; |
| + v8::Handle<v8::Context> context = v8::Context::New(); |
| + context->Enter(); |
| + CalcFibAndCheck(); |
| + { |
| + v8::Locker second_lock(isolate_); |
| + { |
| + context->Exit(); |
| + isolate_->Exit(); |
| + v8::Unlocker unlocker(isolate_); |
| + LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context); |
| + i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
| + thread.StartWithSignal(semaphore); |
| + semaphore->Wait(); |
| + delete semaphore; |
| + } |
| + } |
| + isolate_->Enter(); |
| + context->Enter(); |
| + CalcFibAndCheck(); |
| + } |
|
Vitaly Repeshko
2011/04/15 00:29:39
context->Exit()?
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + private: |
| + v8::Isolate* isolate_; |
| +}; |
| + |
| +TEST(LockTwiceAndUnlock) { |
| + const int kNThreads = 100; |
| + i::List<JoinableThread*> threads(kNThreads); |
| + v8::Isolate* isolate = v8::Isolate::New(); |
| + for (int i = 0; i < kNThreads; i++) { |
| + threads.Add(new LockTwiceAndUnlockThread(isolate)); |
| + } |
| + StartJoinAndDeleteThreads(threads); |
| + isolate->Dispose(); |
| +} |
| + |
| +class LockAndUnlockDifferentIsolatesThread : public JoinableThread { |
| + public: |
| + LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1, |
| + v8::Isolate* isolate2) |
| + : JoinableThread(NULL, "LockAndUnlockDifferentIsolatesThread"), |
| + isolate1_(isolate1), |
| + isolate2_(isolate2) { |
| + } |
| + |
| + void DoRun() { |
| + Persistent<v8::Context> context1; |
| + Persistent<v8::Context> context2; |
| + v8::Locker lock1(isolate1_); |
| + CHECK(v8::Locker::IsLocked(isolate1_)); |
| + CHECK(!v8::Locker::IsLocked(isolate2_)); |
| + { |
| + v8::Isolate::Scope isolate_scope(isolate1_); |
| + v8::HandleScope handle_scope; |
| + context1 = v8::Context::New(); |
| + context1->Enter(); |
| + CalcFibAndCheck(); |
| + context1->Exit(); |
| + } |
| + v8::Locker lock2(isolate2_); |
| + CHECK(v8::Locker::IsLocked(isolate1_)); |
| + CHECK(v8::Locker::IsLocked(isolate2_)); |
| + { |
| + v8::Isolate::Scope isolate_scope(isolate2_); |
| + v8::HandleScope handle_scope; |
| + context2 = v8::Context::New(); |
| + context2->Enter(); |
| + CalcFibAndCheck(); |
| + context2->Exit(); |
| + } |
| + { |
| + v8::Unlocker unlock1(isolate1_); |
| + CHECK(!v8::Locker::IsLocked(isolate1_)); |
| + CHECK(v8::Locker::IsLocked(isolate2_)); |
| + v8::Isolate::Scope isolate_scope(isolate2_); |
| + v8::HandleScope handle_scope; |
| + context2->Enter(); |
| + i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
| + LockIsolateAndCalculateFibSharedContextThread thread(isolate1_, context1); |
| + thread.StartWithSignal(semaphore); |
| + CalcFibAndCheck(); |
| + semaphore->Wait(); |
| + delete semaphore; |
| + context2->Exit(); |
| + } |
| + } |
| + private: |
| + v8::Isolate* isolate1_; |
| + v8::Isolate* isolate2_; |
| +}; |
| + |
| +TEST(LockAndUnlockDifferentIsolates) { |
| + v8::Isolate* isolate1 = v8::Isolate::New(); |
| + v8::Isolate* isolate2 = v8::Isolate::New(); |
| + LockAndUnlockDifferentIsolatesThread thread(isolate1, isolate2); |
| + i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
| + thread.StartWithSignal(semaphore); |
| + semaphore->Wait(); |
| + delete semaphore; |
| + isolate2->Dispose(); |
| + isolate1->Dispose(); |
| +} |
| + |
| +class LockUnlockLockThread : public JoinableThread { |
| + public: |
| + LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context) |
| + : JoinableThread(NULL, "LockUnlockLockThread"), |
| + isolate_(isolate), |
| + context_(context) { |
| + } |
| + |
| + void DoRun() { |
| + v8::Locker lock1(isolate_); |
| + CHECK(v8::Locker::IsLocked(isolate_)); |
| + CHECK(!v8::Locker::IsLocked()); |
| + { |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + v8::HandleScope handle_scope; |
| + context_->Enter(); |
| + CalcFibAndCheck(); |
| + context_->Exit(); |
| + } |
| + { |
| + v8::Unlocker unlock1(isolate_); |
| + CHECK(!v8::Locker::IsLocked(isolate_)); |
| + CHECK(!v8::Locker::IsLocked()); |
| + { |
| + v8::Locker lock2(isolate_); |
| + v8::Isolate::Scope isolate_scope(isolate_); |
| + v8::HandleScope handle_scope; |
| + CHECK(v8::Locker::IsLocked(isolate_)); |
| + CHECK(!v8::Locker::IsLocked()); |
| + context_->Enter(); |
| + CalcFibAndCheck(); |
| + context_->Exit(); |
| + } |
| + } |
| + } |
| + |
| + private: |
| + v8::Isolate* isolate_; |
| + v8::Persistent<v8::Context> context_; |
| +}; |
| + |
| +TEST(LockUnlockLockMultithreaded) { |
| + const int kNThreads = 100; |
| + v8::Isolate* isolate = v8::Isolate::New(); |
| + Persistent<v8::Context> context; |
| + { |
| + v8::Locker locker_(isolate); |
| + v8::Isolate::Scope isolate_scope(isolate); |
| + v8::HandleScope handle_scope; |
| + context = v8::Context::New(); |
| + } |
| + i::List<JoinableThread*> threads(kNThreads); |
| + for (int i = 0; i < kNThreads; i++) { |
| + threads.Add(new LockUnlockLockThread(isolate, context)); |
| + } |
| + StartJoinAndDeleteThreads(threads); |
| +} |
| + |
| +class LockUnlockLockDefaultIsolateThread : public JoinableThread { |
| + public: |
| + LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context) |
| + : JoinableThread(NULL, "LockUnlockLockDefaultIsolateThread"), |
| + context_(context) { |
| + } |
| + |
| + void DoRun() { |
| + v8::Locker lock1; |
| + { |
| + v8::HandleScope handle_scope; |
| + context_->Enter(); |
| + CalcFibAndCheck(); |
| + context_->Exit(); |
| + } |
| + { |
| + v8::Unlocker unlock1; |
| + { |
| + v8::Locker lock2; |
| + v8::HandleScope handle_scope; |
| + context_->Enter(); |
| + CalcFibAndCheck(); |
| + context_->Exit(); |
| + } |
| + } |
| + } |
| + |
| + private: |
| + v8::Persistent<v8::Context> context_; |
| +}; |
| + |
| +TEST(LockUnlockLockDefaultIsolateMultithreaded) { |
| + const int kNThreads = 100; |
| + Persistent<v8::Context> context; |
| + { |
| + v8::Locker locker_; |
| + v8::HandleScope handle_scope; |
| + context = v8::Context::New(); |
| + } |
| + i::List<JoinableThread*> threads(kNThreads); |
| + for (int i = 0; i < kNThreads; i++) { |
| + threads.Add(new LockUnlockLockDefaultIsolateThread(context)); |
| + } |
| + StartJoinAndDeleteThreads(threads); |
| +} |