Index: media/audio/async_socket_io_handler_posix.cc |
diff --git a/media/audio/async_socket_io_handler_posix.cc b/media/audio/async_socket_io_handler_posix.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c4d3169640f2a77ebc4c16011c5afa5778704b2f |
--- /dev/null |
+++ b/media/audio/async_socket_io_handler_posix.cc |
@@ -0,0 +1,89 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/audio/async_socket_io_handler.h" |
+ |
+#include <fcntl.h> |
+#include "base/eintr_wrapper.h" |
+ |
+namespace media { |
+ |
+AsyncSocketIoHandler::AsyncSocketIoHandler() |
+ : socket_(base::SyncSocket::kInvalidHandle), |
+ is_watching_(false) {} |
+ |
+AsyncSocketIoHandler::~AsyncSocketIoHandler() { |
+ DCHECK(CalledOnValidThread()); |
+} |
+ |
+void AsyncSocketIoHandler::OnFileCanReadWithoutBlocking(int socket) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK_EQ(socket, socket_); |
+ if (!read_complete_.is_null()) { |
+ int bytes_read = HANDLE_EINTR(read(socket_, pending_buffer_, |
+ pending_buffer_len_)); |
+ DCHECK_GT(bytes_read, 0); |
+ read_complete_.Run(bytes_read > 0 ? bytes_read : 0); |
+ read_complete_.Reset(); |
+ } else { |
+ // We're getting notifications that we can read from the socket while |
+ // we're not waiting for data. In order to not starve the message loop, |
+ // let's stop watching the fd and restart the watch when Read() is called. |
+ is_watching_ = false; |
+ socket_watcher_.StopWatchingFileDescriptor(); |
+ } |
+} |
+ |
+bool AsyncSocketIoHandler::Read(char* buffer, int buffer_len, |
+ const ReadCompleteCallback& callback) { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK(read_complete_.is_null()); |
+ |
+ EnsureWatchingSocket(); |
+ |
+ int bytes_read = HANDLE_EINTR(read(socket_, buffer, buffer_len)); |
+ if (bytes_read < 0) { |
+ if (errno == EAGAIN) { |
+ read_complete_ = callback; |
+ pending_buffer_ = buffer; |
+ pending_buffer_len_ = buffer_len; |
+ } else { |
+ NOTREACHED() << "read(): " << errno; |
+ return false; |
+ } |
+ } else { |
+ callback.Run(bytes_read); |
+ } |
+ return true; |
+} |
+ |
+bool AsyncSocketIoHandler::Initialize(base::SyncSocket::Handle socket) { |
+ DCHECK_EQ(socket_, base::SyncSocket::kInvalidHandle); |
+ |
+ DetachFromThread(); |
+ |
+ socket_ = socket; |
+ |
+ // SyncSocket is blocking by default, so let's convert it to non-blocking. |
+ int value = fcntl(socket, F_GETFL); |
+ if (!(value & O_NONBLOCK)) { |
+ // Set the socket to be non-blocking so we can do async reads. |
+ if (fcntl(socket, F_SETFL, O_NONBLOCK) == -1) { |
+ NOTREACHED(); |
+ return false; |
+ } |
+ } |
+ |
+ return true; |
+} |
+ |
+void AsyncSocketIoHandler::EnsureWatchingSocket() { |
+ DCHECK(CalledOnValidThread()); |
+ if (!is_watching_ && socket_ != base::SyncSocket::kInvalidHandle) { |
+ is_watching_ = MessageLoopForIO::current()->WatchFileDescriptor( |
+ socket_, true, MessageLoopForIO::WATCH_READ, &socket_watcher_, this); |
+ } |
+} |
+ |
+} // namespace media. |