symbian-qemu-0.9.1-12/python-2.6.1/Modules/_multiprocessing/pipe_connection.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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 
       
    17 static Py_ssize_t
       
    18 conn_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 
       
    35 static Py_ssize_t
       
    36 conn_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 
       
    86 #define conn_poll(conn, timeout) conn_poll_save(conn, timeout, _save)
       
    87 
       
    88 static int
       
    89 conn_poll_save(ConnectionObject *conn, double timeout, PyThreadState *_save)
       
    90 {
       
    91 	DWORD bytes, deadline, delay;
       
    92 	int difference, res;
       
    93 	BOOL block = FALSE;
       
    94 
       
    95 	if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL))
       
    96 		return MP_STANDARD_ERROR;
       
    97 
       
    98 	if (timeout == 0.0)
       
    99 		return bytes > 0;
       
   100 
       
   101 	if (timeout < 0.0)
       
   102 		block = TRUE;
       
   103 	else
       
   104 		/* XXX does not check for overflow */
       
   105 		deadline = GetTickCount() + (DWORD)(1000 * timeout + 0.5);
       
   106 
       
   107 	Sleep(0);
       
   108 
       
   109 	for (delay = 1 ; ; delay += 1) {
       
   110 		if (!PeekNamedPipe(conn->handle, NULL, 0, NULL, &bytes, NULL))
       
   111 			return MP_STANDARD_ERROR;
       
   112 		else if (bytes > 0)
       
   113 			return TRUE;
       
   114 
       
   115 		if (!block) {
       
   116 			difference = deadline - GetTickCount();
       
   117 			if (difference < 0)
       
   118 				return FALSE;
       
   119 			if ((int)delay > difference)
       
   120 				delay = difference;
       
   121 		}
       
   122 
       
   123 		if (delay > 20)
       
   124 			delay = 20;
       
   125 
       
   126 		Sleep(delay);
       
   127 
       
   128 		/* check for signals */
       
   129 		Py_BLOCK_THREADS 
       
   130 		res = PyErr_CheckSignals();
       
   131 		Py_UNBLOCK_THREADS
       
   132 
       
   133 		if (res)
       
   134 			return MP_EXCEPTION_HAS_BEEN_SET;
       
   135 	}
       
   136 }
       
   137 
       
   138 /*
       
   139  * "connection.h" defines the PipeConnection type using the definitions above
       
   140  */
       
   141 
       
   142 #define CONNECTION_NAME "PipeConnection"
       
   143 #define CONNECTION_TYPE PipeConnectionType
       
   144 
       
   145 #include "connection.h"