Dos and Don’ts of the ThreadSafe SwitchKit Library

Behavior of the API

As part of implementing a threadsafe API on top of the existing API, there was a layer of code that was developed to restrict access to the thread unsafe portions of the code. As a result, there are certain behaviors or peculiarities that the application developer should be aware of. Some of the issues are described below.

Sending Messages

Messages that are sent as a result of calling skts_sendMessage(), SKC_Message::tsSend() or any functions which result in messages being sent are actually queued for sending. They are sent by the thread which call skts_rcvAndDispatch()/skts_rcvAndDispatchAutoStorage() (from here on, I will only mention skts_rcvAndDispatch() by name as the functions are nearly identical). The actual send happens quickly. If the thread calling skts_rcvAndDispatch() is blocked on a socket waiting for a message from LLC, the blocking thread will wake up to send any queued up messages and then continue waiting for messages).

SwitchKit Initialization

 

The first SwitchKit function call made must be skts_enableThreadSafeAPI(). The call to skts_enableThreadSafeAPI() must be made in the same thread that the skts_rcvAndDispatch() loop will be implemented in. No other calls to skts_rcvAndDispatch() or any switchkit receive function should be made outside the thread running the skts_rcvAndDispatch() loop. All SwitchKit handlers defined by the application are called within the context of the thread that called skts_rcvAndDispatch(). This thread should normally be blocked waiting for a message from the LLC. When a message arrives, the SwitchKit API code running in that thread will receive the message and determine which handler should receive the message. The SwitchKit API code will call the handler passing in the message just received. Applications wishing to have messages processed by other "worker" threads must arrange to get the message to the worker threads by any means at the application developer’s disposal. The exact mechanism used to get the message to the worker thread is outside the scope of SwitchKit API.

No Mixing of Threadsafe and Non-threadsafe Functions

Applications cannot mix threadsafe and standard SwitchKit functions in a single application. The thread calling skts_rcvAndDispatch() spends some portion of it’s execution path in the non-threadsafe portion of the code. If another thread attempts to access the non-threadsafe portion of the code at the same time, SwitchKit internal data will be corrupted causing your application to behave incorrectly. Therefore, multi-threaded applications must use functions beginning with "skts" or the SKC_Message::tsSend() method and no two threads may call skts_rcvAndDispatch() simultaneously.

Preferred Application Model

Multi-threaded applications developed by Dialogic customers should use the Threadsafe SwitchKit API as has been described in this chapter. The Threadsafe SwitchKit API was designed with an application model consisting of two main components:

The main thread

One or more worker threads.

The Main Thread

The main thread or initial thread of the process is where the application starts execution. Here, all process level initialization takes place. SwitchKit initialization should also take place within the main thread.

Table 12-1 Steps of a Main Thread Process

The main thread should minimally include:

Step

Description

1

Initialize the Threadsafe SwitchKit API by calling skts_enableThreadSafeAPI().

2

Establish connections to all LLCs.

Typical applications connect to only one pair of redundant LLCs, however, in a large distributed environment, the application may be required to connection multiple LLCs. There should be one skts_createConnection() call for each LLC redundant pair in the system and each pair should be assigned a unique connection ID.

3

Setting the main handlers for the application.


This includes the LLC connection handler (skts_setLLCConnectionHandler()), at least one default handler (skts_setDefaultHandler() or skts_pushDefaultHander()) and optionally a group handler (skts_setGroupHandler()) if performing call processing using LLC channel groups.

4

Register for SwitchKit messages.

These messages are switch initiated messages which can present the current state of the switch or the current state of resources and devices on the switch. This registration is performed using skts_msgRegister(), skts_pplComponentRegister(), skts_pplTCAPRegister() or several other function.

5

Optionally, register for inbound calls being presented to LLC channel groups.

This is done using the skts_watchChannelGroup()

6

Spawn worker threads.

More details on worker threads will be provided in the next part of this discussion.

7

Call skts_rcvAndDispatch() or skts_rcvAndDispatchAutoStorage() in a loop.

It is important that one of these two functions be called continuously and often in order to guarantee timely delivery of messages between the application and the LLC in both directions. Failure to call this function often may adversely impact the performance of the application resulting in symptoms including, but not limited to, processing lower than expected call volumes and infrequent to frequent loss of connection to LLC.

All messages sent by the LLC to the application will initially be presented to a handler or will be returned from skts_rcvAndDispatch() or skts_rcvAndDispatchAutoStorage() within the context of the thread calling the aforementioned function (in this case, the main thread). In order for the worker threads to process the message, the message itself or relevant information contained within the message, should be presented to the worker threads so that the bulk of the processing may occur within the context of the worker thread. Failure to do so will result in an application that is more complicated than a single threaded application, and less efficient since it will be unable to leverage the multi-processor platforms commonly used in application deployments.

Worker Threads

Worker threads contain the bulk of the business logic. They must receive work in the form of a message or information extracted from messages, process the work, and possibly send the next message to the CSP that is required to continue processing the transaction. These threads can be designed to perform tasks which are time-consuming and that will otherwise impact the throughput of your application. This may include performing database lookups as part of validating a caller’s right to use the services provided by your application or the level and types of services offered to a caller, ASN.1 encoding and decoding of TCAP message, or any other function which cannot be performed in a very short period of time.

 

Table 12-2 Initialization Sequence for Worker Threads

The next table shows the general structure of a worker thread:

Step

Description

1

Receive work from the main thread. This work can come in the form of a copy of the message received from the main thread or the relevant data from the message received.

2

Process the work.

3

Send any follow-up messages to the switch using skts_sendMessage() or SKC_Message::tsSend() or any other API that results in a message being sent.