TNSDL. TNSDL stands for TeleNokia Specification and Description Language. TNSDL is based on the ITU-T SDL-88 language. It is used exclusively at Nokia Networks, primarily for developing applications for telephone exchanges.

Purpose
TNSDL is a general-purpose procedural programming language. It is especially well-suited for developing highly concurrent, distributed systems.

It was originally designed for programming circuit switched exchanges. As the world shifted towards packet-switched and internet-based telecommunication, TNSDL turned out to be an excellent fit for developing internet servers, too.

Design
TNSDL is a very simple, easy-to-learn programming language.

Basics
TNSDL is a strongly typed procedural programming language. Its basic capabilities are comparable to the C and Pascal languages.

Multi-processing
In TNSDL processes are created by the CREATE command. (It is somewhat similar to the POSIX fork or pthread_create commands.) The CREATE command creates either an operating system process or a cooperative task.

The process model can be selected by configuration. The source code itself does not reflect which scheduling method is used. Still, to avoid certain race conditions, developers may need to be prepared for parallel execution. TNSDL explicitly supports critical sections to be marked in the code.

In case of cooperative multitasking a program is scheduled as one operating system process. When a cooperative thread enters the state of waiting for asynchronous input, another thread of the program may run.

Message passing
The feature of TNSDL is the actor model. Processes are meant to be designed as event-driven finite state machines. Inter-process communication is done by asynchronous message passing. The OUTPUT command sends a message, while INPUT statements define the expected messages.

Timers, from TNSDL perspective, are delayed messages. Just like ordinary messages, timer expiration is handled by the INPUT statement. The SET command starts and the RESET command cancels a timer.

State machines can be optionally used, for example, to prevent accepting certain input messages at some stage of the processing.

The following code piece demonstrates a server, which receives a query signal (message), contacts a database process to obtain the necessary data and finally sends an answer signal.

DCL WITHWARMING /* Data to be live-migrated (on platforms supporting "warming") */
  query_process pid; /* PID of query_signal sender */

CONSTANT time_to_wait = 10; /* Timeout of database response */

TIMER db_timeout_timer; /* Timer of database response */

STATE idle; /* Idle state, wait for query signal */
  INPUT query_signal(DCL input_data);
    DCL
      db_query db_query_type;     /* Local variable, stored on stack. */
    TASK query_process := SENDER; /* Sender address saved to specific memory area, which is preserved even on software update.*/
    TASK db_query.field1 := some_procedure(input_data),
         db_query.field2 := input_data.field1;
    OUTPUT db_request_signal(db_query) TO db_process; /* Send request to database process */
    SET(NOW + time_to_wait, db_timeout_timer);        /* Start database response timer */
    NEXTSTATE wait_db;                                /* Enter wait_db state where database response is expected */
ENDSTATE idle;

STATE wait_db;
  INPUT db_response_signal(DCL answer_data);
    RESET(db_timeout_timer) COMMENT 'Database answered in time';
    OUTPUT answer_signal(answer_data.records) TO query_process;
    NEXTSTATE idle;

  INPUT db_timeout_timer; /* Timeout */
    OUTPUT error_signal(error_constant) TO query_process;
    NEXTSTATE idle;
ENDSTATE wait_db;

Comments:
 The state machine prevents any new query_signal to be processed while waiting for the database program to answer.
 WITHWARMING means that when another computer takes over the role of the current one, the marked data (variable) will be copied to the new computer. Therefore, if hardware change or software update happens while waiting for the database to answer, the address of the query sender will not be lost, and the answer can be delivered properly. It is not supported on all platforms, though.

TNSDL allows inputs to be tied to several or all of the states. An input signal may have state-specific behavior, if needed.

STATE idle COMMENT 'Idle state';
  INPUT are_you_busy;
    OUTPUT no TO SENDER;
    NEXTSTATE -; /* No state change */
  /* ... other input handlers */
ENDSTATE idle;

STATE *(idle) COMMENT 'Any state, except idle';
  INPUT are_you_busy;
    OUTPUT yes TO SENDER;
    NEXTSTATE -; /* No state change */
ENDSTATE *(idle);

STATE * COMMENT 'Any state';
  INPUT are_you_alive;
    OUTPUT yes TO SENDER;
    NEXTSTATE -; /* No state change */
ENDSTATE *;

Differences from SDL-88

Nokia has made several modifications to the language, mainly including simplifications and additions, such as:

 Features like channels and signal routes have been replaced by other mechanisms.
 The concepts of modules and services were added in TNSDL (the service concept of SDL-88 is similar to the subautomaton feature of TNSDL). 
 Some elements have been renamed (for example Priority Inputs are called Input Internals in TNSDL). 
 In TNSDL the MACRO feature has been omitted and a WHILE construct has been added to allow loops in a structured way without using JOINs.

Compiling
TNSDL is not directly compiled to machine code. Instead, TNSDL programs are translated to C language source code. The responsibility of TNSDL is to allow message handling, state machine definitions, synchronizing parallel execution, "data warming" etc. easily and safely coded. The task of processor-specific code generation and low-level optimization is delegated to the C compiler used.

After translating TNSDL to C, any standard-compliant C compiler, linker, coverage measurement and profiling tool can be used. To make source-level debugging possible TNSDL puts line number references to the generated C code.

TNSDL code can call routines implemented in other languages, if objects or libraries are present for them. Even C language macros can be used, if C header files are present. External declarations must be made available to the TNSDL translator.

The TNSDL translator is a proprietary tool. A source code (reachability) analyser has also been developed specifically for TNSDL.

Use
TNSDL is commonly used on the DX 200, IPA 2800 and Linux platforms for high-performance, high-availability applications.

TNSDL is an actively used and developed programming language used by thousands of developers (in 2010).

TNSDL is mainly used at Nokia Networks for developing software for SGSNs, BSCs, mobile switching centers, application servers both in traditional setups and as virtual network functions (VNF) of NFV solutions.

Similar programming languages 
Despite the difference in syntax, probably one of the closest relative of TNSDL is Go language. Both languages has light-weight processes in their focus. Go's channel are similar to TNSDL INPUTs and Go's select statement on channels allows very similar program design. There are differences, though. TNSDL uses asynchronous message passing between actors, while channels in Go can either be synchronous or asynchronous (buffered). TNSDL allows message passing between processes running on the same or separate computer nodes. In that aspect TNSDL is a relative of Erlang.

Even though in TNSDL one can define operators for types and protect structure attributes to be accessible via those operators only, TNSDL is not an object-oriented language. In that aspect it belongs to the family of non-OOP procedural programming languages, such as C language.

History
1980s: In the beginning, ITU-T SDL had a graphical syntax. Textual syntax was introduced later. A corresponding graphical tool and code generator were developed within Nokia.

1990: ITU-T SDL shifted towards text-based representation. Based on the SDL-88 specification TNSDL was born. TNSDL is a simplified and heavily customized variant of SDL-88.

References

Formal specification languages
Procedural programming languages
Programming languages created in the 1980s