Index: pjproject/trunk/pjlib/include/pj/ioqueue.h
===================================================================
--- pjproject/trunk/pjlib/include/pj/ioqueue.h	(revision 54)
+++ pjproject/trunk/pjlib/include/pj/ioqueue.h	(revision 55)
@@ -234,4 +234,10 @@
 #   define PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL     (16)
 #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)
 
 /**
@@ -506,5 +512,6 @@
  *                  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
@@ -519,5 +526,5 @@
 				      void *buffer,
 				      pj_ssize_t *length,
-				      unsigned flags );
+				      pj_uint32_t flags );
 
 /**
@@ -543,5 +550,6 @@
  *                  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.
@@ -561,5 +569,5 @@
 					  void *buffer,
 					  pj_ssize_t *length,
-                                          unsigned flags,
+                                          pj_uint32_t flags,
 					  pj_sockaddr_t *addr,
 					  int *addrlen);
@@ -588,5 +596,6 @@
  *                  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
@@ -602,5 +611,5 @@
 				      const void *data,
 				      pj_ssize_t *length,
-				      unsigned flags );
+				      pj_uint32_t flags );
 
 
@@ -628,5 +637,6 @@
  *                  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.
@@ -641,5 +651,5 @@
 					const void *data,
 					pj_ssize_t *length,
-                                        unsigned flags,
+                                        pj_uint32_t flags,
 					const pj_sockaddr_t *addr,
 					int addrlen);
Index: pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c
===================================================================
--- pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c	(revision 54)
+++ pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c	(revision 55)
@@ -492,6 +492,4 @@
 				      unsigned flags )
 {
-    pj_status_t status;
-    pj_ssize_t size;
     struct read_operation *read_op;
 
@@ -504,17 +502,24 @@
     /* 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);
 
     /*
@@ -548,6 +553,4 @@
 				         int *addrlen)
 {
-    pj_status_t status;
-    pj_ssize_t size;
     struct read_operation *read_op;
 
@@ -560,18 +563,25 @@
     /* 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);
 
     /*
@@ -614,4 +624,7 @@
     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:
@@ -676,5 +689,5 @@
 			               const void *data,
 			               pj_ssize_t *length,
-                                       unsigned flags,
+                                       pj_uint32_t flags,
 			               const pj_sockaddr_t *addr,
 			               int addrlen)
@@ -689,4 +702,7 @@
     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:
Index: pjproject/trunk/pjlib/src/pj/ioqueue_winnt.c
===================================================================
--- pjproject/trunk/pjlib/src/pj/ioqueue_winnt.c	(revision 54)
+++ pjproject/trunk/pjlib/src/pj/ioqueue_winnt.c	(revision 55)
@@ -530,5 +530,5 @@
 				      void *buffer,
 				      pj_ssize_t *length,
-				      unsigned flags )
+				      pj_uint32_t flags )
 {
     /*
@@ -554,16 +554,20 @@
      * 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);
 
     /*
@@ -599,5 +603,5 @@
 					 void *buffer,
 					 pj_ssize_t *length,
-                                         unsigned flags,
+                                         pj_uint32_t flags,
 					 pj_sockaddr_t *addr,
 					 int *addrlen)
@@ -620,16 +624,20 @@
      * 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);
 
     /*
@@ -665,5 +673,5 @@
 				      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);
@@ -680,5 +688,5 @@
 				       const void *data,
 				       pj_ssize_t *length,
-                                       unsigned flags,
+                                       pj_uint32_t flags,
 				       const pj_sockaddr_t *addr,
 				       int addrlen)
@@ -694,6 +702,4 @@
     op_key_rec = (union operation_key*)op_key->internal__;
 
-    dwFlags = flags;
-
     /*
      * First try blocking write.
@@ -702,17 +708,23 @@
     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);
 
     /*
