LPFN_RIOCREATECOMPLETIONQUEUE回调函数 (mswsock.h)

RIOCreateCompletionQueue 函数创建特定大小的 I/O 完成队列,用于 Winsock 注册的 I/O 扩展。

语法

LPFN_RIOCREATECOMPLETIONQUEUE LpfnRiocreatecompletionqueue;

RIO_CQ LpfnRiocreatecompletionqueue(
  DWORD QueueSize,
  PRIO_NOTIFICATION_COMPLETION NotificationCompletion
)
{...}

参数

QueueSize

要创建的完成队列的大小(以条目数为单位)。

NotificationCompletion

基于 I/O 完成或事件通知 ) (RIO_NOTIFICATION_COMPLETION结构的 Type 成员使用的通知完成类型。

如果 Type 成员设置为 RIO_EVENT_COMPLETION,则必须设置 RIO_NOTIFICATION_COMPLETION 结构的 Event 成员。

如果 Type 成员设置为 RIO_IOCP_COMPLETION,则必须设置 RIO_NOTIFICATION_COMPLETION 结构的 Iocp 成员,并且 RIO_NOTIFICATION_COMPLETION 结构的 Iocp.Overlapped 成员不得为 NULL。

如果 NotificationCompletion 参数为 NULL,则指定不使用通知完成,并且必须使用轮询来确定完成。

返回值

如果未发生错误, RIOCreateCompletionQueue 函数将返回引用新完成队列的描述符。 否则,将返回 值 RIO_INVALID_CQ ,并且可以通过调用 WSAGetLastError 函数来检索特定的错误代码。

返回代码 说明
WSAEFAULT
系统尝试在调用中使用指针参数时检测到指针地址无效。
WSAEINVAL
向该函数传递了无效参数。
如果 QueueSize 参数小于 1 或大于 Mswsockdef.h 头文件中定义的RIO_MAX_CQ_SIZE,则返回此错误。
WSAENOBUFS
无法分配足够的内存。 如果内存不足,无法分配基于 QueueSize 参数请求的完成队列,则返回此错误。

注解

RIOCreateCompletionQueue 函数创建特定大小的 I/O 完成队列。 完成队列的大小限制可与完成队列关联的已注册 I/O 套接字集。 有关详细信息,请参阅 RIOCreateRequestQueue 函数。

创建RIO_CQ时,NotificationCompletion 参数指向的RIO_NOTIFICATION_COMPLETION结构确定应用程序接收完成队列通知的方式。 如果在创建完成队列时提供了 RIO_NOTIFICATION_COMPLETION 结构,应用程序可能会调用 RIONotify 函数来请求完成队列通知。 通常,当完成队列不为空时,会发生此通知。 这可能会立即发生,或者在将下一个完成项插入完成队列时发生。 但是,发送和接收请求可能会标记为 RIO_MSG_DONT_NOTIFY。 完成队列通知 和 永远不会因此类请求而触发。 如果完成队列仅包含设置了 RIO_MSG_DONT_NOTIFY 标志的条目,则不会触发完成队列通知。 此外,当新条目进入完成队列时,只有在关联的请求中未设置 RIO_MSG_DONT_NOTIFY 标志时,才会触发完成队列通知。 仍可使用 RIODequeueCompletion 函数轮询来检索任何已完成的请求。 发出完成队列通知后,应用程序必须调用 RIONotify 函数才能接收另一个完成队列通知。 发生完成队列通知时,应用程序通常会调用 RIODequeueCompletion 函数来取消已完成的发送或接收请求的排队。

有两个选项可用于完成队列通知。

  • 事件句柄。
  • I/O 完成端口

如果RIO_NOTIFICATION_COMPLETION结构的 Type 成员设置为 RIO_EVENT_COMPLETION,则事件句柄用于向完成队列通知发出信号。 事件句柄作为传递给 RIOCreateCompletionQueue 函数的 RIO_NOTIFICATION_COMPLETION 结构中的 EventNotify.EventHandle 成员提供。 Event.EventHandle 成员应包含由 WSACreateEventCreateEvent 函数创建的事件的句柄。 若要接收 RIONotify 完成,应用程序应使用 WSAWaitForMultipleEvents 或类似的等待例程等待指定的事件句柄。 此RIO_CQRIONotify 函数完成将发出事件信号。 传递给 RIOCreateCompletionQueue 函数的 RIO_NOTIFICATION_COMPLETION 结构中的 Event.NotifyReset 成员指示是否应在调用 RIONotify 函数时重置事件。 如果应用程序计划重置并重复使用事件,则应用程序可以通过将 Event.NotifyReset 成员设置为非零值来减少开销。 这会导致发生通知时 ,RIONotify 函数自动重置事件。 这减少了调用 WSAResetEvent 函数以在调用 RIONotify 函数之间重置事件的需求。

如果RIO_NOTIFICATION_COMPLETION结构的 Type 成员设置为 RIO_IOCP_COMPLETION,则 I/O 完成端口用于发出完成队列通知的信号。 I/O 完成端口句柄作为传递给 RIOCreateCompletionQueue 函数的 RIO_NOTIFICATION_COMPLETION 结构中的 Iocp.IocpHandle 成员提供。 此RIO_CQRIONotify 函数的完成会将 I/O 完成端口的条目排队,可以使用 GetQueuedCompletionStatusGetQueuedCompletionStatusEx 函数检索该条目。 排队条目会将返回的 lpCompletionKey 参数值设置为 RIO_NOTIFICATION_COMPLETION 结构的 Iocp.CompletionKey 成员中指定的值,RIO_NOTIFICATION_COMPLETION 结构中的 Iocp.Overlapped 成员将是非 NULL 值。

就其用法而言,完成队列通知旨在唤醒等待的应用程序线程,以便线程可以检查完成队列。 唤醒和计划线程会产生成本,因此,如果这种情况发生得太频繁,将对应用程序性能产生负面影响。 提供了 RIO_MSG_DONT_NOTIFY 标志,以便应用程序可以控制这些事件的频率,并限制它们对性能的过度影响。

注意

为了提高效率,对完成队列的访问 (RIO_CQ 结构) 和请求队列 (RIO_RQ 结构) 不受同步基元的保护。 如果需要从多个线程访问完成队列或请求队列,应通过关键部分、精简读取器写入锁或类似机制协调访问。 单个线程访问不需要此锁定。 不同的线程可以在没有锁的情况下访问单独的请求/完成队列。 仅当多个线程尝试访问同一队列时,才需要同步。 如果多个线程在同一套接字上发出发送和接收,则还需要同步,因为发送和接收操作使用套接字的请求队列。

 

注意

必须在运行时通过调用 WSAIoctl 函数并指定SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER操作码来获取指向 RIOCreateCompletionQueue 函数的函数指针。 传递给 WSAIoctl 函数的输入缓冲区必须包含 WSAID_MULTIPLE_RIO,这是一个全局唯一标识符, (GUID) 其值标识 Winsock 注册的 I/O 扩展函数。 成功后, WSAIoctl 函数返回的输出包含指向 RIO_EXTENSION_FUNCTION_TABLE 结构的指针,该结构包含指向 Winsock 注册的 I/O 扩展函数的指针。 SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER IOCTL 在 Ws2def.h 头文件中定义。 WSAID_MULTIPLE_RIO GUID 在 Mswsock.h 头文件中定义。

 

Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。

要求

要求
Header mswsock.h