This chapter describes an overview of PiaTransport and the details of its internal operations.
Several communications formats (such as UDP, TCP, and IP telephony) of different characters exist even though they are all using the same communications channels. Pia provides protocols for each format to enable efficient communications.
The transport::Protocol class is available as a base class for Pia protocols, and there are different derived classes for each of the different types of communications (such as transport::UnreliableProtocol, transport::ReliableProtocol, and chat::VoiceProtocol).
When an application communicates between stations, it creates an instance of the appropriate Pia protocol, and calls the send and receive APIs of that instance.
When PiaTransport is set up, send and receive threads are created. The relationship between these threads and the send and receive APIs for each protocol as called by the application thread is indicated in the following figure.
In simple terms, the send operations are as follows.
Similarly, receive operations are summarized as follows.
Generally speaking, API calls that cause I/O access tend to block for long periods of time. As mentioned previously, however, with PiaTransport, the send and receive threads call SDK send and receive APIs. As a result, the application thread does not block by the SDK send and receive API calls.
The previous description was a summary. This section describes a detailed description of the dispatch function and the send and receive processes and threads as they occur in PiaTransport.
PiaTransport includes a dispatch function that is responsible for the following processes.
This dispatch function is implicitly called from the nn::pia::common::Scheduler::Dispatch() function. Pia does not work normally unless dispatching occurs at regular intervals. The application must call the nn::pia::common::Scheduler::Dispatch() function at an interval of once or twice each frame.
Send processes occur as follows.
The corresponding receive processes occur as follows.
The operations of the send and receive threads are indicated in the following pseudocode.
while(true)
{ if(isSendPacketExist()) { // Continues to call the send function as long as there are packets to send. send(packet); } else { // Puts the send thread to sleep when there are no longer any packets to send. sleep(sendThreadSleepSpan); } } |
while(true)
{ if(isReceivePacketExist()) { // Continues to call the receive function as long as there are packets to receive. receive(&packet); } else { // Puts the receive thread to sleep when there are no longer any packets to receive. sleep(receiveThreadSleepSpan); } } |
The send and receive threads have relatively high priorities, so they send and receive packets on a regular basis. Sending and receiving block the thread, so the execution right is passed to the lower priority threads (such as the main thread). In addition, when there are no longer any packets to send or receive, the send and receive threads go to sleep, and thread execution rights shift to another thread.
You can specify the sleep intervals for the send and receive threads with the transport::ThreadStreamManager::SetSendThreadSleepTimeSpan() and transport::ThreadStreamManager::SetReceiveThreadSleepTimeSpan() functions. Setting a shorter sleep interval reduces the time that data can store up, and might improve the program's responsiveness. Frequent thread switching, however, can increase the overall load on the CPU.
Any delay in assigning a CPU to the Pia sending and receiving threads could have a negative effect on Pia system operations.
The application can specify a different priority for the send and receive threads. Normally, however, set the priority higher than the priority of the thread that the application uses to call the Pia APIs. If the application creates any threads with a higher priority than the Pia sending and receiving threads, you must exercise caution to avoid monopolizing the CPU for an extended period of time.