Thread-specific Data Handling Routines - Example

This program initializes a thread-storage handle and then starts off several threads which each use the handle to access thread local data. Consistency checks are made within each entry to ts-test, on termination of each thread and on termination of the run-unit. This program takes advantage of the Thread-Local-Storage Section, external data items, exit procedures and basic synchronization to achieve this function.

Source Code

$set reentrant sourceformat(free)
 copy "cblproto.cpy".

************************************************************ 
* tstore-main.                                             * 
* Main routine to initialize tables and kick off threads.  *
*                                                          *
************************************************************ 

 program-id. 'tstore'. 
 environment division. 
 special-names. command-line is cmdln. 
 
 working-storage section. 
 78 THREAD-COUNT VALUE 5. 

 01 tstore-handle    cblt-pointer is external. 
 01 c-0              cblt-x1-compx.
 01 foo-item         pic 9(9) value 0. 
 01 thredid          pic xxxx comp-5. 
 01 thread-handle    cblt-pointer.
 01 thread-entry     cblt-ppointer.

 01 exitparms        cblt-exit-params.

 thread-local-storage section. 
 01 filler. 
     05 tl-count pic x value 'x'. 
     05 tl-ptr   cblt-pointer. 

 linkage section. 
 01 tstore-item. 
     05 filler       pic x. 
       88 TSTORE-INIT VALUE 'Y'. 
     05 tstore-count pic 999. 

 procedure division. 
*> 
*> Initialize thread table and set up for clean exit 
*>    
     call "CBL_TSTORE_CREATE" using         tstore-handle 
                            by value length tstore-item 
                            by value        h'04' 
*> 
*> Set up for clean exit 
*> 
     move low-values  to exitparms
     set cblte-ep-install-addr   to entry 'exitproc'
     move 0    to c-0 
     call 'CBL_EXIT_PROC'    using c-0 exitparms

     call 'ts-get'           using tl-ptr 
     set address of tstore-item to tl-ptr 
     move THREAD-COUNT   to tstore-count 
     set thread-entry    to entry "ts-entry"
     move 1    to thredid 
     perform THREAD-COUNT times    
         call "CBL_THREAD_CREATE_P" using by value thread-entry
           by reference thredid 
           by value length of thredid 
           by value     0 
           by value     0 
           by value     0 
           by reference thread-handle 
         if return-code not = 0 
             call 'CBL_THREAD_PROG_LOCK' 
             display "FAIL: Cannot create thread" 
             call 'CBL_THREAD_PROG_UNLOCK' 
             stop run 
         end-if 
         add 1 to thredid 
     end-perform 
     stop run. 


 entry "exitproc".
     call "CBL_TSTORE_GET" using by value     tstore-handle 
                                 by reference tl-ptr 
     set address of tstore-item to tl-ptr 
     if tl-ptr = NULL
     or not TSTORE-INIT 
     or tstore-count not = THREAD-COUNT 
         display "FAIL: TSTORE not initialized properly!" 
     else 
         display "PASS: Main thread has count " tstore-count 
     end-if 
     call "CBL_TSTORE_CLOSE" using by value tstore-handle 
     exit program. 

 end program 'tstore'. 

************************************************************ 
*                                                          *
* ts-entry.                                                * 
* Root entry point for threads created by application.     * 
*                                                          *
************************************************************ 
 program-id. 'ts-entry'. 
 working-storage section. 
 78 REP-COUNT VALUE 5. 

 01 tl-ptr   cblt-pointer.

 linkage section. 
 01 lnk-thredid pic xxxx comp-5. 

 01 tstore-item.
     05 filler pic x. 
         88 TSTORE-INIT VALUE 'Y'. 
     05 tstore-count pic 999. 
  
 procedure division using lnk-thredid. 
 thread-section. 
     perform REP-COUNT times 
         call 'ts-test' using lnk-thredid 
     end-perform 
 
     call 'ts-get'  using tl-ptr 
     set address of tstore-item to tl-ptr 
  
     call "CBL_THREAD_PROG_LOCK" 
     if tstore-count not = REP-COUNT 
        display "FAIL: Thread storage rep-count BAD" 
     else 
        display "PASS: Thread storage rep-count good" 
     end-if 
     call "CBL_THREAD_PROG_UNLOCK" 
     exit program. 
 end program 'ts-entry'. 

************************************************************ 
*                                                          *   
* ts-test.                                                 * 
* Routine to get a thread storage area and increment its   *
* count                                                    * 
*                                                          *
************************************************************ 
 program-id. 'ts-test'. 
 
 working-storage section. 
 01 global-count pic 99999 value 0. 
 
 thread-local-storage section. 
 01 tl-ptr     cblt-pointer.
 01 tl-count   pic 999 value 0. 

 linkage section. 
 01 lnk-thredid  pic xxxx comp-5. 
 
 01 tstore-item. 
   05 filler   pic x. 
       88 TSTORE-INIT VALUE 'Y'. 
   05 tstore-count  pic 999. 
 procedure division using lnk-thredid. 
 thread-section. 
     call 'ts-get'   using tl-ptr 
     set address of tstore-item    to tl-ptr 
     add 1       to tstore-count 
     add 1       to tl-count 
 
     if tstore-count not = tl-count 
         display "ERROR: inconsistent thread local data" 
         stop run 
     end-if 
 
     call "CBL_THREAD_PROG_LOCK" 
     add 1 to global-count 
     display "MESSAGE: thread-test has been called " tstore-count 
         " by thread " lnk-thredid 
     display "MESSAGE: thread-test has been called " global-count " globally " 
     call "CBL_THREAD_PROG_UNLOCK" 
  
     exit program. 
 
 end program 'ts-test'. 

************************************************************ 
* ts-get.                                                  * 
* Common routine to get and initialize the thread storage  * 
* area allocated by CBL_TSTORE_GET.                        * 
*                                                          *
************************************************************ 
 program-id. 'ts-get'. 
 data division. 
 working-storage section. 
 01 tstore-handle cblt-pointer external. 
 
 thread-local-storage section. 
 01 tl-ptr    cblt-pointer.
 
 linkage section. 
 01 tstore-item. 
     05 filler       pic x. 
         88 TSTORE-INIT VALUE 'Y'. 
     05 tstore-count pic 999. 
 01 lnk-ptr usage pointer. 

 procedure division using lnk-ptr. 
     call "CBL_TSTORE_GET" using by value     tstore-handle 
                                 by reference tl-ptr 
     if tl-ptr = NULL 
         display "FAIL: Error in getting thread " & 
                 "storage data" 
         stop run 
     end-if 
     set address of tstore-item to tl-ptr 
     if not TSTORE-INIT 
         move 0 to tstore-count 
     end-if 
     set tstore-init to true 
     set lnk-ptr to tl-ptr 

 exit program. 

 end program 'ts-get'.