diff options
author | sehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-26 00:28:02 +0000 |
---|---|---|
committer | sehr@google.com <sehr@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-26 00:28:02 +0000 |
commit | 182c44faa58c15e474682f2ad349eca5a6a2235f (patch) | |
tree | 183ecce85bf6f84b4b9ed77ae358103ede765864 /base/sync_socket_posix.cc | |
parent | 4ebb4f136e3e5040351b4e29ca79fe1153ce606d (diff) | |
download | chromium_src-182c44faa58c15e474682f2ad349eca5a6a2235f.zip chromium_src-182c44faa58c15e474682f2ad349eca5a6a2235f.tar.gz chromium_src-182c44faa58c15e474682f2ad349eca5a6a2235f.tar.bz2 |
Implement SyncSocket class for Posix targets (Linux, Mac), and enable the
corresponding unittest. This feature, as a reminder, allows low-latency
(blocking) send/receive between processes, and will be used for real-time
thread synchronization for Pepper audio and for direct synchronization for
3D video.
Review URL: http://codereview.chromium.org/431043
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33161 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/sync_socket_posix.cc')
-rw-r--r-- | base/sync_socket_posix.cc | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/base/sync_socket_posix.cc b/base/sync_socket_posix.cc new file mode 100644 index 0000000..35d53b2 --- /dev/null +++ b/base/sync_socket_posix.cc @@ -0,0 +1,101 @@ +// Copyright (c) 2009 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 "base/sync_socket.h" + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "base/atomicops.h" +#include "base/file_util.h" +#include "base/logging.h" + + +namespace base { + +namespace { +// To avoid users sending negative message lengths to Send/Receive +// we clamp message lengths, which are size_t, to no more than INT_MAX. +const size_t kMaxMessageLength = static_cast<size_t>(INT_MAX); + +static const SyncSocket::Handle kInvalidHandle = -1; + +} // namespace + +bool SyncSocket::CreatePair(SyncSocket* pair[2]) { + Handle handles[2] = { kInvalidHandle, kInvalidHandle }; + SyncSocket* tmp_sockets[2] = { NULL, NULL }; +#if defined(OS_MACOSX) + int nosigpipe = 1; +#endif // defined(OS_MACOSX) + + // Create the two SyncSocket objects first to avoid ugly cleanup issues. + tmp_sockets[0] = new SyncSocket(kInvalidHandle); + if (tmp_sockets[0] == NULL) { + goto cleanup; + } + tmp_sockets[1] = new SyncSocket(kInvalidHandle); + if (tmp_sockets[1] == NULL) { + goto cleanup; + } + if (socketpair(AF_UNIX, SOCK_STREAM, 0, handles) != 0) { + goto cleanup; + } +#if defined(OS_MACOSX) + // On OSX an attempt to read or write to a closed socket may generate a + // SIGPIPE rather than returning -1. setsockopt will shut this off. + if (0 != setsockopt(handles[0], SOL_SOCKET, SO_NOSIGPIPE, + &nosigpipe, sizeof nosigpipe) || + 0 != setsockopt(handles[1], SOL_SOCKET, SO_NOSIGPIPE, + &nosigpipe, sizeof nosigpipe)) { + goto cleanup; + } +#endif + // Copy the handles out for successful return. + tmp_sockets[0]->handle_ = handles[0]; + pair[0] = tmp_sockets[0]; + tmp_sockets[1]->handle_ = handles[1]; + pair[1] = tmp_sockets[1]; + return true; + +cleanup: + if (handles[0] != kInvalidHandle) + (void) close(handles[0]); + if (handles[1] != kInvalidHandle) + (void) close(handles[1]); + delete tmp_sockets[0]; + delete tmp_sockets[1]; + return false; +} + +bool SyncSocket::Close() { + if (handle_ == kInvalidHandle) { + return false; + } + int retval = close(handle_); + handle_ = kInvalidHandle; + return (retval == 0); +} + +size_t SyncSocket::Send(const void* buffer, size_t length) { + DCHECK(length <= kMaxMessageLength); + const char* charbuffer = static_cast<const char*>(buffer); + int len = file_util::WriteFileDescriptor(handle_, charbuffer, length); + return static_cast<size_t>(len); +} + +size_t SyncSocket::Receive(void* buffer, size_t length) { + DCHECK(length <= kMaxMessageLength); + char* charbuffer = static_cast<char*>(buffer); + if (file_util::ReadFromFD(handle_, charbuffer, length)) { + return length; + } else { + return -1; + } +} + +} // namespace base |