summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2005-11-19 13:19:28 +0000
committerBenny Prijono <bennylp@teluu.com>2005-11-19 13:19:28 +0000
commit2b228d36e3852f3a857ec2c73c056ca3a8f90025 (patch)
tree5c99f4042f1c53ae86cd9184f3a6cd97a1a874bf
parent9e1924d579a65c21db21e76d227582bb9474bb57 (diff)
Added PJ_IOQUEUE_ALWAYS_ASYNC flag
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@55 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/include/pj/ioqueue.h26
-rw-r--r--pjlib/src/pj/ioqueue_common_abs.c76
-rw-r--r--pjlib/src/pj/ioqueue_winnt.c92
3 files changed, 116 insertions, 78 deletions
diff --git a/pjlib/include/pj/ioqueue.h b/pjlib/include/pj/ioqueue.h
index 2bc34d87..26484cad 100644
--- a/pjlib/include/pj/ioqueue.h
+++ b/pjlib/include/pj/ioqueue.h
@@ -235,6 +235,12 @@ typedef enum pj_ioqueue_operation_e
#endif
/**
+ * When this flag is specified in ioqueue's recv() or send() operations,
+ * the ioqueue will always mark the operation as asynchronous.
+ */
+#define PJ_IOQUEUE_ALWAYS_ASYNC ((pj_uint32_t)1 << (pj_uint32_t)31)
+
+/**
* Return the name of the ioqueue implementation.
*
* @return Implementation name.
@@ -505,7 +511,8 @@ PJ_DECL(int) pj_ioqueue_poll( pj_ioqueue_t *ioque,
* callback. This parameter can point to local variable in
* caller's stack and doesn't have to remain valid for the
* duration of pending operation.
- * @param flags Recv flag.
+ * @param flags Recv flag. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then
+ * the function will never return PJ_SUCCESS.
*
* @return
* - PJ_SUCCESS If immediate data has been received in the buffer. In this
@@ -518,7 +525,7 @@ PJ_DECL(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
void *buffer,
pj_ssize_t *length,
- unsigned flags );
+ pj_uint32_t flags );
/**
* This function behaves similarly as #pj_ioqueue_recv(), except that it is
@@ -542,7 +549,8 @@ PJ_DECL(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
* callback. This parameter can point to local variable in
* caller's stack and doesn't have to remain valid for the
* duration of pending operation.
- * @param flags Recv flag.
+ * @param flags Recv flag. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then
+ * the function will never return PJ_SUCCESS.
* @param addr Optional Pointer to buffer to receive the address.
* @param addrlen On input, specifies the length of the address buffer.
* On output, it will be filled with the actual length of
@@ -560,7 +568,7 @@ PJ_DECL(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
void *buffer,
pj_ssize_t *length,
- unsigned flags,
+ pj_uint32_t flags,
pj_sockaddr_t *addr,
int *addrlen);
@@ -587,7 +595,8 @@ PJ_DECL(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
* number of bytes sent. This parameter can point to local
* variable on caller's stack and doesn't have to remain
* valid until the operation has completed.
- * @param flags Send flags.
+ * @param flags Send flags. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then
+ * the function will never return PJ_SUCCESS.
*
* @return
* - PJ_SUCCESS If data was immediately transfered. In this case, no
@@ -601,7 +610,7 @@ PJ_DECL(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
- unsigned flags );
+ pj_uint32_t flags );
/**
@@ -627,7 +636,8 @@ PJ_DECL(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
* number of bytes sent. This parameter can point to local
* variable on caller's stack and doesn't have to remain
* valid until the operation has completed.
- * @param flags send flags.
+ * @param flags send flags. If flags has PJ_IOQUEUE_ALWAYS_ASYNC then
+ * the function will never return PJ_SUCCESS.
* @param addr Optional remote address.
* @param addrlen Remote address length, \c addr is specified.
*
@@ -640,7 +650,7 @@ PJ_DECL(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
- unsigned flags,
+ pj_uint32_t flags,
const pj_sockaddr_t *addr,
int addrlen);
diff --git a/pjlib/src/pj/ioqueue_common_abs.c b/pjlib/src/pj/ioqueue_common_abs.c
index 14966466..b383a31f 100644
--- a/pjlib/src/pj/ioqueue_common_abs.c
+++ b/pjlib/src/pj/ioqueue_common_abs.c
@@ -491,8 +491,6 @@ PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
pj_ssize_t *length,
unsigned flags )
{
- pj_status_t status;
- pj_ssize_t size;
struct read_operation *read_op;
PJ_ASSERT_RETURN(key && op_key && buffer && length, PJ_EINVAL);
@@ -503,20 +501,27 @@ PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
/* Try to see if there's data immediately available.
*/
- size = *length;
- status = pj_sock_recv(key->fd, buffer, &size, flags);
- if (status == PJ_SUCCESS) {
- /* Yes! Data is available! */
- *length = size;
- return PJ_SUCCESS;
- } else {
- /* If error is not EWOULDBLOCK (or EAGAIN on Linux), report
- * the error to caller.
- */
- if (status != PJ_STATUS_FROM_OS(PJ_BLOCKING_ERROR_VAL))
- return status;
+ if ((flags & PJ_IOQUEUE_ALWAYS_ASYNC) == 0) {
+ pj_status_t status;
+ pj_ssize_t size;
+
+ size = *length;
+ status = pj_sock_recv(key->fd, buffer, &size, flags);
+ if (status == PJ_SUCCESS) {
+ /* Yes! Data is available! */
+ *length = size;
+ return PJ_SUCCESS;
+ } else {
+ /* If error is not EWOULDBLOCK (or EAGAIN on Linux), report
+ * the error to caller.
+ */
+ if (status != PJ_STATUS_FROM_OS(PJ_BLOCKING_ERROR_VAL))
+ return status;
+ }
}
+ flags &= ~(PJ_IOQUEUE_ALWAYS_ASYNC);
+
/*
* No data is immediately available.
* Must schedule asynchronous operation to the ioqueue.
@@ -547,8 +552,6 @@ PJ_DEF(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
pj_sockaddr_t *addr,
int *addrlen)
{
- pj_status_t status;
- pj_ssize_t size;
struct read_operation *read_op;
PJ_ASSERT_RETURN(key && op_key && buffer && length, PJ_EINVAL);
@@ -559,21 +562,28 @@ PJ_DEF(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
/* Try to see if there's data immediately available.
*/
- size = *length;
- status = pj_sock_recvfrom(key->fd, buffer, &size, flags,
- addr, addrlen);
- if (status == PJ_SUCCESS) {
- /* Yes! Data is available! */
- *length = size;
- return PJ_SUCCESS;
- } else {
- /* If error is not EWOULDBLOCK (or EAGAIN on Linux), report
- * the error to caller.
- */
- if (status != PJ_STATUS_FROM_OS(PJ_BLOCKING_ERROR_VAL))
- return status;
+ if ((flags & PJ_IOQUEUE_ALWAYS_ASYNC) == 0) {
+ pj_status_t status;
+ pj_ssize_t size;
+
+ size = *length;
+ status = pj_sock_recvfrom(key->fd, buffer, &size, flags,
+ addr, addrlen);
+ if (status == PJ_SUCCESS) {
+ /* Yes! Data is available! */
+ *length = size;
+ return PJ_SUCCESS;
+ } else {
+ /* If error is not EWOULDBLOCK (or EAGAIN on Linux), report
+ * the error to caller.
+ */
+ if (status != PJ_STATUS_FROM_OS(PJ_BLOCKING_ERROR_VAL))
+ return status;
+ }
}
+ flags &= ~(PJ_IOQUEUE_ALWAYS_ASYNC);
+
/*
* No data is immediately available.
* Must schedule asynchronous operation to the ioqueue.
@@ -614,6 +624,9 @@ PJ_DEF(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
write_op = (struct write_operation*)op_key;
write_op->op = 0;
+ /* We can not use PJ_IOQUEUE_ALWAYS_ASYNC for socket write. */
+ flags &= ~(PJ_IOQUEUE_ALWAYS_ASYNC);
+
/* Fast track:
* Try to send data immediately, only if there's no pending write!
* Note:
@@ -675,7 +688,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
- unsigned flags,
+ pj_uint32_t flags,
const pj_sockaddr_t *addr,
int addrlen)
{
@@ -689,6 +702,9 @@ PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
write_op = (struct write_operation*)op_key;
write_op->op = 0;
+ /* We can not use PJ_IOQUEUE_ALWAYS_ASYNC for socket write */
+ flags &= ~(PJ_IOQUEUE_ALWAYS_ASYNC);
+
/* Fast track:
* Try to send data immediately, only if there's no pending write!
* Note:
diff --git a/pjlib/src/pj/ioqueue_winnt.c b/pjlib/src/pj/ioqueue_winnt.c
index 65aaf2e9..828b568e 100644
--- a/pjlib/src/pj/ioqueue_winnt.c
+++ b/pjlib/src/pj/ioqueue_winnt.c
@@ -529,7 +529,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
void *buffer,
pj_ssize_t *length,
- unsigned flags )
+ pj_uint32_t flags )
{
/*
* Ideally we should just call pj_ioqueue_recvfrom() with NULL addr and
@@ -553,19 +553,23 @@ PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key,
/* Try non-overlapped received first to see if data is
* immediately available.
*/
- rc = WSARecv((SOCKET)key->hnd, &op_key_rec->overlapped.wsabuf, 1,
- &bytesRead, &dwFlags, NULL, NULL);
- if (rc == 0) {
- *length = bytesRead;
- return PJ_SUCCESS;
- } else {
- DWORD dwError = WSAGetLastError();
- if (dwError != WSAEWOULDBLOCK) {
- *length = -1;
- return PJ_RETURN_OS_ERROR(dwError);
- }
+ if ((flags & PJ_IOQUEUE_ALWAYS_ASYNC) == 0) {
+ rc = WSARecv((SOCKET)key->hnd, &op_key_rec->overlapped.wsabuf, 1,
+ &bytesRead, &dwFlags, NULL, NULL);
+ if (rc == 0) {
+ *length = bytesRead;
+ return PJ_SUCCESS;
+ } else {
+ DWORD dwError = WSAGetLastError();
+ if (dwError != WSAEWOULDBLOCK) {
+ *length = -1;
+ return PJ_RETURN_OS_ERROR(dwError);
+ }
+ }
}
+ dwFlags &= ~(PJ_IOQUEUE_ALWAYS_ASYNC);
+
/*
* No immediate data available.
* Register overlapped Recv() operation.
@@ -598,7 +602,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
void *buffer,
pj_ssize_t *length,
- unsigned flags,
+ pj_uint32_t flags,
pj_sockaddr_t *addr,
int *addrlen)
{
@@ -619,19 +623,23 @@ PJ_DEF(pj_status_t) pj_ioqueue_recvfrom( pj_ioqueue_key_t *key,
/* Try non-overlapped received first to see if data is
* immediately available.
*/
- rc = WSARecvFrom((SOCKET)key->hnd, &op_key_rec->overlapped.wsabuf, 1,
- &bytesRead, &dwFlags, addr, addrlen, NULL, NULL);
- if (rc == 0) {
- *length = bytesRead;
- return PJ_SUCCESS;
- } else {
- DWORD dwError = WSAGetLastError();
- if (dwError != WSAEWOULDBLOCK) {
- *length = -1;
- return PJ_RETURN_OS_ERROR(dwError);
- }
+ if ((flags & PJ_IOQUEUE_ALWAYS_ASYNC) == 0) {
+ rc = WSARecvFrom((SOCKET)key->hnd, &op_key_rec->overlapped.wsabuf, 1,
+ &bytesRead, &dwFlags, addr, addrlen, NULL, NULL);
+ if (rc == 0) {
+ *length = bytesRead;
+ return PJ_SUCCESS;
+ } else {
+ DWORD dwError = WSAGetLastError();
+ if (dwError != WSAEWOULDBLOCK) {
+ *length = -1;
+ return PJ_RETURN_OS_ERROR(dwError);
+ }
+ }
}
+ dwFlags &= ~(PJ_IOQUEUE_ALWAYS_ASYNC);
+
/*
* No immediate data available.
* Register overlapped Recv() operation.
@@ -664,7 +672,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_send( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
- unsigned flags )
+ pj_uint32_t flags )
{
return pj_ioqueue_sendto(key, op_key, data, length, flags, NULL, 0);
}
@@ -679,7 +687,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
pj_ioqueue_op_key_t *op_key,
const void *data,
pj_ssize_t *length,
- unsigned flags,
+ pj_uint32_t flags,
const pj_sockaddr_t *addr,
int addrlen)
{
@@ -693,28 +701,32 @@ PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key,
op_key_rec = (union operation_key*)op_key->internal__;
- dwFlags = flags;
-
/*
* First try blocking write.
*/
op_key_rec->overlapped.wsabuf.buf = (void*)data;
op_key_rec->overlapped.wsabuf.len = *length;
- rc = WSASendTo((SOCKET)key->hnd, &op_key_rec->overlapped.wsabuf, 1,
- &bytesWritten, dwFlags, addr, addrlen,
- NULL, NULL);
- if (rc == 0) {
- *length = bytesWritten;
- return PJ_SUCCESS;
- } else {
- DWORD dwStatus = WSAGetLastError();
- if (dwStatus != WSAEWOULDBLOCK) {
- *length = -1;
- return PJ_RETURN_OS_ERROR(dwStatus);
- }
+ dwFlags = flags;
+
+ if ((flags & PJ_IOQUEUE_ALWAYS_ASYNC) == 0) {
+ rc = WSASendTo((SOCKET)key->hnd, &op_key_rec->overlapped.wsabuf, 1,
+ &bytesWritten, dwFlags, addr, addrlen,
+ NULL, NULL);
+ if (rc == 0) {
+ *length = bytesWritten;
+ return PJ_SUCCESS;
+ } else {
+ DWORD dwStatus = WSAGetLastError();
+ if (dwStatus != WSAEWOULDBLOCK) {
+ *length = -1;
+ return PJ_RETURN_OS_ERROR(dwStatus);
+ }
+ }
}
+ dwFlags &= ~(PJ_IOQUEUE_ALWAYS_ASYNC);
+
/*
* Data can't be sent immediately.
* Schedule asynchronous WSASend().