PageRenderTime 26ms CodeModel.GetById 13ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/Modules/_multiprocessing/pipe_connection.c

http://unladen-swallow.googlecode.com/
C | 143 lines | 91 code | 29 blank | 23 comment | 25 complexity | a608d152a11d9f27356b536c5750072d MD5 | raw file
  1/*
  2 * A type which wraps a pipe handle in message oriented mode
  3 *
  4 * pipe_connection.c
  5 *
  6 * Copyright (c) 2006-2008, R Oudkerk --- see COPYING.txt
  7 */
  8
  9#include "multiprocessing.h"
 10
 11#define CLOSE(h) CloseHandle(h)
 12
 13/*
 14 * Send string to the pipe; assumes in message oriented mode
 15 */
 16
 17static Py_ssize_t
 18conn_send_string(ConnectionObject *conn, char *string, size_t length)
 19{
 20	DWORD amount_written;
 21	BOOL ret;
 22
 23	Py_BEGIN_ALLOW_THREADS
 24	ret = WriteFile(conn->handle, string, length, &amount_written, NULL);
 25	Py_END_ALLOW_THREADS
 26	return ret ? MP_SUCCESS : MP_STANDARD_ERROR;
 27}
 28
 29/*
 30 * Attempts to read into buffer, or if buffer too small into *newbuffer.
 31 *
 32 * Returns number of bytes read.  Assumes in message oriented mode.
 33 */
 34
 35static Py_ssize_t
 36conn_recv_string(ConnectionObject *conn, char *buffer, 
 37		 size_t buflength, char **newbuffer, size_t maxlength)
 38{
 39	DWORD left, length, full_length, err;
 40	BOOL ret;
 41	*newbuffer = NULL;
 42
 43	Py_BEGIN_ALLOW_THREADS
 44	ret = ReadFile(conn->handle, buffer, MIN(buflength, maxlength), 
 45		      &length, NULL);
 46	Py_END_ALLOW_THREADS
 47	if (ret)
 48		return length;
 49
 50	err = GetLastError();
 51	if (err != ERROR_MORE_DATA) {
 52		if (err == ERROR_BROKEN_PIPE)
 53			return MP_END_OF_FILE;
 54		return MP_STANDARD_ERROR;
 55	}
 56
 57	if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, NULL, &left))
 58		return MP_STANDARD_ERROR;
 59
 60	full_length = length + left;
 61	if (full_length > maxlength)
 62		return MP_BAD_MESSAGE_LENGTH;
 63
 64	*newbuffer = PyMem_Malloc(full_length);
 65	if (*newbuffer == NULL)
 66		return MP_MEMORY_ERROR;
 67
 68	memcpy(*newbuffer, buffer, length);
 69
 70	Py_BEGIN_ALLOW_THREADS
 71	ret = ReadFile(conn->handle, *newbuffer+length, left, &length, NULL);
 72	Py_END_ALLOW_THREADS
 73	if (ret) {
 74		assert(length == left);
 75		return full_length;
 76	} else {
 77		PyMem_Free(*newbuffer);
 78		return MP_STANDARD_ERROR;
 79	}
 80}
 81
 82/*
 83 * Check whether any data is available for reading
 84 */
 85
 86static int
 87conn_poll(ConnectionObject *conn, double timeout, PyThreadState *_save)
 88{
 89	DWORD bytes, deadline, delay;
 90	int difference, res;
 91	BOOL block = FALSE;
 92
 93	if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL))
 94		return MP_STANDARD_ERROR;
 95
 96	if (timeout == 0.0)
 97		return bytes > 0;
 98
 99	if (timeout < 0.0)
100		block = TRUE;
101	else
102		/* XXX does not check for overflow */
103		deadline = GetTickCount() + (DWORD)(1000 * timeout + 0.5);
104
105	Sleep(0);
106
107	for (delay = 1 ; ; delay += 1) {
108		if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL))
109			return MP_STANDARD_ERROR;
110		else if (bytes > 0)
111			return TRUE;
112
113		if (!block) {
114			difference = deadline - GetTickCount();
115			if (difference < 0)
116				return FALSE;
117			if ((int)delay > difference)
118				delay = difference;
119		}
120
121		if (delay > 20)
122			delay = 20;
123
124		Sleep(delay);
125
126		/* check for signals */
127		Py_BLOCK_THREADS 
128		res = PyErr_CheckSignals();
129		Py_UNBLOCK_THREADS
130
131		if (res)
132			return MP_EXCEPTION_HAS_BEEN_SET;
133	}
134}
135
136/*
137 * "connection.h" defines the PipeConnection type using the definitions above
138 */
139
140#define CONNECTION_NAME "PipeConnection"
141#define CONNECTION_TYPE PipeConnectionType
142
143#include "connection.h"