Chromium Code Reviews| Index: src/d8.cc |
| diff --git a/src/d8.cc b/src/d8.cc |
| index 0b737c6ffe291e6913269f0618d4608127fe5210..ecf790ff68c66d76da823b27690ff5c622c7132c 100644 |
| --- a/src/d8.cc |
| +++ b/src/d8.cc |
| @@ -1609,6 +1609,7 @@ void SerializationDataQueue::Enqueue(SerializationData* data) { |
| bool SerializationDataQueue::Dequeue(SerializationData** data) { |
| base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| + *data = NULL; |
| if (data_.is_empty()) return false; |
| *data = data_.Remove(0); |
| return true; |
| @@ -1662,7 +1663,9 @@ void Worker::PostMessage(SerializationData* data) { |
| SerializationData* Worker::GetMessage() { |
| SerializationData* data = NULL; |
| while (!out_queue_.Dequeue(&data)) { |
| - if (base::NoBarrier_Load(&state_) != RUNNING) break; |
| + // If the worker is no longer running, and there are no messages in the |
| + // queue, don't expect any more messages from it. |
| + if (base::NoBarrier_Load(&state_) > RUNNING) break; |
| out_semaphore_.Wait(); |
| } |
| @@ -1671,14 +1674,53 @@ SerializationData* Worker::GetMessage() { |
| void Worker::Terminate() { |
| - if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { |
| + if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATING) == |
| + RUNNING) { |
| // Post NULL to wake the Worker thread message loop. |
| PostMessage(NULL); |
| - thread_->Join(); |
| } |
| } |
| +void Worker::WaitForThread() { |
| + Terminate(); |
| + |
| + State expected_state = TERMINATING; |
| + while (true) { |
| + State actual_state = static_cast<State>( |
| + base::NoBarrier_CompareAndSwap(&state_, expected_state, JOINING)); |
| + |
| + if (actual_state == expected_state) break; |
| + |
| + switch (actual_state) { |
| + case IDLE: |
| + case RUNNING: |
| + // We terminated above, we should never be IDLE or RUNNING. |
| + UNREACHABLE(); |
| + return; |
| + |
| + case TERMINATING: |
| + case STOPPED: |
|
Jarin
2015/07/10 10:43:17
Why do we want to retry when STOPPED?
Actually, I
binji
2015/07/10 17:40:46
You're right, this is too complicated. I refactore
|
| + // Try again. |
| + expected_state = actual_state; |
| + break; |
| + |
| + case JOINING: |
|
Jarin
2015/07/10 10:43:17
Is not this only called when the shell finishes, s
binji
2015/07/10 17:40:46
True, this was just caution to prevent multiple jo
|
| + // Someone else is joining. Bail. |
| + return; |
| + |
| + case JOINED: |
| + // Tried to join twice. |
| + UNREACHABLE(); |
| + return; |
| + } |
| + } |
| + |
| + thread_->Join(); |
| + base::NoBarrier_Store(&state_, JOINED); |
| +} |
| + |
| + |
| void Worker::ExecuteInThread() { |
| Isolate::CreateParams create_params; |
| create_params.array_buffer_allocator = Shell::array_buffer_allocator; |
| @@ -1741,11 +1783,10 @@ void Worker::ExecuteInThread() { |
| } |
| isolate->Dispose(); |
| - if (base::NoBarrier_CompareAndSwap(&state_, RUNNING, TERMINATED) == RUNNING) { |
| - // Post NULL to wake the thread waiting on GetMessage() if there is one. |
| - out_queue_.Enqueue(NULL); |
| - out_semaphore_.Signal(); |
| - } |
| + base::NoBarrier_Store(&state_, STOPPED); |
| + // Post NULL to wake the thread waiting on GetMessage() if there is one. |
| + out_queue_.Enqueue(NULL); |
| + out_semaphore_.Signal(); |
| } |
| @@ -2143,18 +2184,12 @@ MaybeLocal<Value> Shell::DeserializeValue(Isolate* isolate, |
| break; |
| case kSerializationTagString: { |
| int length = data.Read<int>(offset); |
| - static char s_buffer[128]; |
|
binji
2015/07/09 00:13:12
I'm pretty ashamed of this one... :-|
|
| - char* p = s_buffer; |
| - bool allocated = false; |
| - if (length > static_cast<int>(sizeof(s_buffer))) { |
| - p = new char[length]; |
| - allocated = true; |
| - } |
| + char* p = new char[length]; |
|
Jarin
2015/07/10 10:43:17
How about using std::vector<char> here, instead of
binji
2015/07/10 17:40:46
Done (though I was not sure that std containers we
|
| data.ReadMemory(p, length, offset); |
| MaybeLocal<String> str = |
| String::NewFromUtf8(isolate, p, String::kNormalString, length); |
| if (!str.IsEmpty()) result = str.ToLocalChecked(); |
| - if (allocated) delete[] p; |
| + delete[] p; |
| break; |
| } |
| case kSerializationTagArray: { |
| @@ -2226,7 +2261,7 @@ void Shell::CleanupWorkers() { |
| for (int i = 0; i < workers_copy.length(); ++i) { |
| Worker* worker = workers_copy[i]; |
| - worker->Terminate(); |
| + worker->WaitForThread(); |
| delete worker; |
| } |