| Index: runtime/bin/process.h
|
| diff --git a/runtime/bin/process.h b/runtime/bin/process.h
|
| index 48cf21bbb271c8cea87bd33b2cc0a18a5f162216..f877b8d51bd55dc37722648b56e1ce7ed22d9e4e 100644
|
| --- a/runtime/bin/process.h
|
| +++ b/runtime/bin/process.h
|
| @@ -5,11 +5,16 @@
|
| #ifndef RUNTIME_BIN_PROCESS_H_
|
| #define RUNTIME_BIN_PROCESS_H_
|
|
|
| +#include <errno.h>
|
| +
|
| #include "bin/builtin.h"
|
| #include "bin/io_buffer.h"
|
| #include "bin/lockers.h"
|
| #include "bin/thread.h"
|
| #include "platform/globals.h"
|
| +#if !defined(TARGET_OS_WINDOWS)
|
| +#include "platform/signal_blocker.h"
|
| +#endif
|
| #include "platform/utils.h"
|
|
|
| namespace dart {
|
| @@ -203,24 +208,30 @@ class BufferListBase {
|
| public:
|
| explicit BufferListNode(intptr_t size) {
|
| data_ = new uint8_t[size];
|
| - if (data_ == NULL) FATAL("Allocation failed");
|
| + // We check for a failed allocation below in Allocate()
|
| next_ = NULL;
|
| }
|
|
|
| ~BufferListNode() { delete[] data_; }
|
|
|
| + bool Valid() const { return data_ != NULL; }
|
| +
|
| + uint8_t* data() const { return data_; }
|
| + BufferListNode* next() const { return next_; }
|
| + void set_next(BufferListNode* n) { next_ = n; }
|
| +
|
| + private:
|
| uint8_t* data_;
|
| BufferListNode* next_;
|
|
|
| - private:
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(BufferListNode);
|
| };
|
|
|
| public:
|
| BufferListBase() : head_(NULL), tail_(NULL), data_size_(0), free_size_(0) {}
|
| ~BufferListBase() {
|
| - ASSERT(head_ == NULL);
|
| - ASSERT(tail_ == NULL);
|
| + Free();
|
| + DEBUG_ASSERT(IsEmpty());
|
| }
|
|
|
| // Returns the collected data as a Uint8List. If an error occours an
|
| @@ -234,9 +245,9 @@ class BufferListBase {
|
| return result;
|
| }
|
| for (BufferListNode* current = head_; current != NULL;
|
| - current = current->next_) {
|
| + current = current->next()) {
|
| intptr_t to_copy = dart::Utils::Minimum(data_size_, kBufferSize);
|
| - memmove(buffer + buffer_position, current->data_, to_copy);
|
| + memmove(buffer + buffer_position, current->data(), to_copy);
|
| buffer_position += to_copy;
|
| data_size_ -= to_copy;
|
| }
|
| @@ -245,26 +256,36 @@ class BufferListBase {
|
| return result;
|
| }
|
|
|
| +#if defined(DEBUG)
|
| + bool IsEmpty() const { return (head_ == NULL) && (tail_ == NULL); }
|
| +#endif
|
| +
|
| protected:
|
| - void Allocate() {
|
| + bool Allocate() {
|
| ASSERT(free_size_ == 0);
|
| BufferListNode* node = new BufferListNode(kBufferSize);
|
| + if ((node == NULL) || !node->Valid()) {
|
| + // Failed to allocate a buffer for the node.
|
| + delete node;
|
| + return false;
|
| + }
|
| if (head_ == NULL) {
|
| head_ = node;
|
| tail_ = node;
|
| } else {
|
| - ASSERT(tail_->next_ == NULL);
|
| - tail_->next_ = node;
|
| + ASSERT(tail_->next() == NULL);
|
| + tail_->set_next(node);
|
| tail_ = node;
|
| }
|
| free_size_ = kBufferSize;
|
| + return true;
|
| }
|
|
|
| void Free() {
|
| BufferListNode* current = head_;
|
| while (current != NULL) {
|
| BufferListNode* tmp = current;
|
| - current = current->next_;
|
| + current = current->next();
|
| delete tmp;
|
| }
|
| head_ = NULL;
|
| @@ -275,9 +296,19 @@ class BufferListBase {
|
|
|
| // Returns the address of the first byte in the free space.
|
| uint8_t* FreeSpaceAddress() {
|
| - return tail_->data_ + (kBufferSize - free_size_);
|
| + return tail_->data() + (kBufferSize - free_size_);
|
| }
|
|
|
| + intptr_t data_size() const { return data_size_; }
|
| + void set_data_size(intptr_t size) { data_size_ = size; }
|
| +
|
| + intptr_t free_size() const { return free_size_; }
|
| + void set_free_size(intptr_t size) { free_size_ = size; }
|
| +
|
| + BufferListNode* head() const { return head_; }
|
| + BufferListNode* tail() const { return tail_; }
|
| +
|
| + private:
|
| // Linked list for data collected.
|
| BufferListNode* head_;
|
| BufferListNode* tail_;
|
| @@ -288,10 +319,49 @@ class BufferListBase {
|
| // Number of free bytes in the last node in the list.
|
| intptr_t free_size_;
|
|
|
| - private:
|
| DISALLOW_COPY_AND_ASSIGN(BufferListBase);
|
| };
|
|
|
| +#if defined(TARGET_OS_ANDROID) || defined(TARGET_OS_FUCHSIA) || \
|
| + defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS)
|
| +class BufferList : public BufferListBase {
|
| + public:
|
| + BufferList() {}
|
| +
|
| + bool Read(int fd, intptr_t available) {
|
| + // Read all available bytes.
|
| + while (available > 0) {
|
| + if (free_size() == 0) {
|
| + if (!Allocate()) {
|
| + errno = ENOMEM;
|
| + return false;
|
| + }
|
| + }
|
| + ASSERT(free_size() > 0);
|
| + ASSERT(free_size() <= kBufferSize);
|
| + intptr_t block_size = dart::Utils::Minimum(free_size(), available);
|
| +#if defined(TARGET_OS_FUCHSIA)
|
| + intptr_t bytes = NO_RETRY_EXPECTED(
|
| + read(fd, reinterpret_cast<void*>(FreeSpaceAddress()), block_size));
|
| +#else
|
| + intptr_t bytes = TEMP_FAILURE_RETRY(
|
| + read(fd, reinterpret_cast<void*>(FreeSpaceAddress()), block_size));
|
| +#endif // defined(TARGET_OS_FUCHSIA)
|
| + if (bytes < 0) {
|
| + return false;
|
| + }
|
| + set_data_size(data_size() + bytes);
|
| + set_free_size(free_size() - bytes);
|
| + available -= bytes;
|
| + }
|
| + return true;
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(BufferList);
|
| +};
|
| +#endif // defined(TARGET_OS_ANDROID) ...
|
| +
|
| } // namespace bin
|
| } // namespace dart
|
|
|
|
|