4. Initialization Settings (Thread Models, Exclusive Control, and Local Communication)

This chapter describes NEX initialization settings.

4.1. Threading Model

NEX gives you the flexibility of choosing a threading model according to your game's specifications.

NEX is designed to perform internal processing and send and receive packets by periodically executing the Scheduler::Dispatch function. Taking into account the CPU load and blocking time of the Scheduler::Dispatch function, We recommend using a thread-unsafe transport buffer thread mode.

4.1.1. Setting the Thread Mode

4.1.1.1. Recommended Settings

We recommend the following NEX settings and usage of other API functions. These settings generally make NEX run in a single thread, eliminating wasteful locking and minimizing the CPU load. Use these settings unless you have a specific reason not to do so.

  • Thread Settings
  • NEX usage
    • Only a thread-unsafe memory allocator can be used.
    • Either use all NEX API functions from the same thread, or if you call them from multiple threads, have the application handle exclusion as appropriate.
    • The application calls the Scheduler::Dispatch or the Scheduler::DispatchAll function at the beginning and end of the frame.

Note

Because operating system processes for sending and receiving packets block for several milliseconds, processing for sending and receiving packets through the operating system API are handled in separate threads to lessen the effect of extended blocking inside Scheduler::Dispatch. Under NEX, such threads are called transport buffer threads.

The transport buffer thread never manipulates memory, because NEX allocates the memory that the thread requires before starting it. Also, NEX and the transport buffer thread are exclusive of each other regardless of the thread mode.

4.1.1.2. Thread Modes

The Core::SetThreadMode function is an easy way to configure the thread mode for the NEX library. There are two thread mode settings: ThreadModeUnsafeTransportBuffer and hreadModeSafeTransportBuffer.

ThreadModeUndefined

This undefined value is used as the initial value.

ThreadModeUnsafeTransportBuffer

The application must periodically execute the Scheduler::Dispatch function. The transport buffer thread starts.

The CPU load is low because exclusive control (CriticalSection) inside NEX other than that with the transport buffer thread is disabled. You must either use all NEX API functions from the same thread or locking in the application, as appropriate. You can use a fast, thread-unsafe memory allocator.

ThreadModeSafeTransportBuffer

The application must periodically execute the Scheduler::Dispatch function. The transport buffer thread starts.

The CPU load is higher because exclusive control (CriticalSection) inside NEX is enabled.

You must use a thread-safe memory allocator when you are executing the Scheduler::Dispatch function and running duplicated object operations in another thread and exclusive control obtained by the Scheduler::SystemLock function in the application is required.

ThreadModeUnsafeUser

The application must periodically execute the Scheduler::Dispatch function. The socket calls in the Scheduler::Dispatch function can block for several milliseconds. Call the Scheduler::Dispatch function from a thread other than the main thread.

The CPU load is low because exclusive control (CriticalSection) inside NEX is disabled. You must either use all NEX API functions from the same thread or locking in the application, as appropriate. You can use a fast, thread-unsafe memory allocator.

4.1.2. Exclusive Control Used to Get Scheduler::SystemLock

In addition to a thread-safe setting (ThreadModeSafeTransportBuffer), exclusive control is also required to get Scheduler::SystemLock when getting or setting duplicated object parameters from another thread calling Scheduler::Dispatch.

4.1.2.1. Example of Using Scheduler::SystemLock

The following sample code shows how to get a list of stations.

Code 4.1 Example of NEX Locking by Application

{
    // The application must perform locking as follows. because it accesses the duplicated object directly.
    ScopedCS oCS(Scheduler::GetInstance()->SystemLock());

    for (nn::nex::Station::SelectionIterator station;!station.EndReached();++station)
    {
        if (!station->IsLocal())
        {
            // Perform on `Station` objects other than self.
        }
    }
}

Warning

Because Station::SelectionIterator is failsafe, an assertion results when initialization is performed without executing the Scheduler::GetInstance function followed by the SystemLock function.

4.1.2.2. API Functions Requiring Exclusion Using Scheduler::SystemLock

The following API function must be excluded using Scheduler::SystemLock().

4.1.2.3. Duplicated Object-related API Functions Not Requiring Exclusion Using Scheduler::SystemLock

The following duplicated object-related API functions do not require exclusion using Scheduler::SystemLock(). DirectStream, NetZ, and API functions unrelated to duplicated objects, such as Core, do not require exclusion using Scheduler::SystemLock().

4.1.2.4. Non Thread-Safe Functions

The following functions cannot be called from multiple threads simultaneously. Do not simultaneously call two or more of the following functions or any combination thereof across all threads.

4.1.3. Thread Stacks

Either the nn::os::Thread::TryStartUsingAutoStack or the nn::os::Thread::TryStart function is used when generating threads. The nn::os::Thread::TryStartUsingAutoStack function is used only when true has been specified for the argument of the nn::nex::Core::UseThreadAutoStack function.

Use the nn::os::Thread::TryStart function when the nn::nex::Core::UseThreadAutoStack function has not been called, or the argument of the nn::nex::Core::UseThreadAutoStack function has been set to false. In this case, the NEX library provides a thread stack that uses the memory-allocation functions registered using the nn::nex::MemoryManager::SetBasicMemoryFunctions function.

  • Stack size passed to nn::os::Thread::TryStartUsingAutoStack: 28 KB
  • Stack size passed to nn::os::Thread::TryStart: 28 KB (Approximately 32 KB (32 KB - 1 byte) of memory is actually allocated)
  • Maximum number of threads in transport buffer thread mode: 3

4.2. Local Communication Link Feature

The local communication link feature enables NetZ operations on other networks. By using the NetZ linked features in the Pia library, NetZ can be operated over a local communications network. This feature enables you to standardize applications that use local P2P communication and applications that use Internet P2P communication.

For more information, see the PiaLocal section in the Pia Programming Manual.


CONFIDENTIAL