mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-12 06:08:24 +02:00
The consumer thread handles socket creation, destruction, and data processing for socket IPC. Traditionally this has been done on the main thread. This patch extends the socket IPC classes to support arbitrary consumer threads. The thread is configured when establishing a connection, and performs all of the above operations until the socket is closed.
124 lines
2.7 KiB
C++
124 lines
2.7 KiB
C++
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
|
/* vim: set ts=2 et sw=2 tw=80: */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "mozilla/ipc/DataSocket.h"
|
|
#ifdef MOZ_TASK_TRACER
|
|
#include "GeckoTaskTracer.h"
|
|
#endif
|
|
|
|
#ifdef MOZ_TASK_TRACER
|
|
using namespace mozilla::tasktracer;
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
namespace ipc {
|
|
|
|
//
|
|
// DataSocketIO
|
|
//
|
|
|
|
DataSocketIO::~DataSocketIO()
|
|
{ }
|
|
|
|
void
|
|
DataSocketIO::EnqueueData(UnixSocketIOBuffer* aBuffer)
|
|
{
|
|
if (!aBuffer->GetSize()) {
|
|
delete aBuffer; // delete empty data immediately
|
|
return;
|
|
}
|
|
mOutgoingQ.AppendElement(aBuffer);
|
|
}
|
|
|
|
bool
|
|
DataSocketIO::HasPendingData() const
|
|
{
|
|
return !mOutgoingQ.IsEmpty();
|
|
}
|
|
|
|
ssize_t
|
|
DataSocketIO::ReceiveData(int aFd)
|
|
{
|
|
MOZ_ASSERT(aFd >= 0);
|
|
|
|
UnixSocketIOBuffer* incoming;
|
|
nsresult rv = QueryReceiveBuffer(&incoming);
|
|
if (NS_FAILED(rv)) {
|
|
/* an error occured */
|
|
GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
|
|
NS_DISPATCH_NORMAL);
|
|
return -1;
|
|
}
|
|
|
|
ssize_t res = incoming->Receive(aFd);
|
|
if (res < 0) {
|
|
/* an I/O error occured */
|
|
DiscardBuffer();
|
|
GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
|
|
NS_DISPATCH_NORMAL);
|
|
return -1;
|
|
} else if (!res) {
|
|
/* EOF or peer shut down sending */
|
|
DiscardBuffer();
|
|
GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
|
|
NS_DISPATCH_NORMAL);
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MOZ_TASK_TRACER
|
|
/* Make unix socket creation events to be the source events of TaskTracer,
|
|
* and originate the rest correlation tasks from here.
|
|
*/
|
|
AutoSourceEvent taskTracerEvent(SourceEventType::Unixsocket);
|
|
#endif
|
|
|
|
ConsumeBuffer();
|
|
|
|
return res;
|
|
}
|
|
|
|
nsresult
|
|
DataSocketIO::SendPendingData(int aFd)
|
|
{
|
|
MOZ_ASSERT(aFd >= 0);
|
|
|
|
while (HasPendingData()) {
|
|
UnixSocketIOBuffer* outgoing = mOutgoingQ.ElementAt(0);
|
|
|
|
ssize_t res = outgoing->Send(aFd);
|
|
if (res < 0) {
|
|
/* an I/O error occured */
|
|
GetConsumerThread()->Dispatch(new SocketIORequestClosingRunnable(this),
|
|
NS_DISPATCH_NORMAL);
|
|
return NS_ERROR_FAILURE;
|
|
} else if (!res && outgoing->GetSize()) {
|
|
/* I/O is currently blocked; try again later */
|
|
return NS_OK;
|
|
}
|
|
if (!outgoing->GetSize()) {
|
|
mOutgoingQ.RemoveElementAt(0);
|
|
delete outgoing;
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
DataSocketIO::DataSocketIO(nsIThread* aConsumerThread)
|
|
: SocketIOBase(aConsumerThread)
|
|
{ }
|
|
|
|
//
|
|
// DataSocket
|
|
//
|
|
|
|
DataSocket::~DataSocket()
|
|
{ }
|
|
|
|
}
|
|
}
|