You can use embedded SQL statements in multi-threaded or reentrant code. However, if you use a single connection, you are restricted to one active request per connection. In a multi-threaded application, you should not use the same connection to the database on each thread unless you use a semaphore to control access.
There are no restrictions on using separate connections on each thread that wants to use the database. The SQLCA is used by the runtime library to distinguish between the different thread contexts. So, each thread wanting to use the database concurrently must have its own SQLCA.
Any given database connection is accessible only from one SQLCA, with the exception of the cancel instruction, which must be issued from a separate thread.
For information about canceling requests, see Implementing request management.
The following is an example of multi-threaded embedded SQL reentrant code.
#include <stdio.h> #include <string.h> #include <malloc.h> #include <ctype.h> #include <stdlib.h> #include <process.h> #include <windows.h> EXEC SQL INCLUDE SQLCA; EXEC SQL INCLUDE SQLDA; #define TRUE 1 #define FALSE 0 // multithreading support typedef struct a_thread_data { SQLCA sqlca; int num_iters; int thread; int done; } a_thread_data; // each thread's ESQL test EXEC SQL SET SQLCA "&thread_data->sqlca"; static void PrintSQLError( a_thread_data * thread_data ) /******************************************************/ { char buffer[200]; printf( "%d: SQL error %d -- %s ... aborting\n", thread_data->thread, SQLCODE, sqlerror_message( &thread_data->sqlca, buffer, sizeof( buffer ) ) ); exit( 1 ); } EXEC SQL WHENEVER SQLERROR { PrintSQLError( thread_data ); }; static void do_one_iter( void * data ) { a_thread_data * thread_data = (a_thread_data *)data; int i; EXEC SQL BEGIN DECLARE SECTION; char user[ 20 ]; EXEC SQL END DECLARE SECTION; if( db_init( &thread_data->sqlca ) != 0 ) { for( i = 0; i < thread_data->num_iters; i++ ) { EXEC SQL CONNECT "dba" IDENTIFIED BY "sql"; EXEC SQL SELECT USER INTO :user; EXEC SQL DISCONNECT; } printf( "Thread %d did %d iters successfully\n", thread_data->thread, thread_data->num_iters ); db_fini( &thread_data->sqlca ); } thread_data->done = TRUE; } int main() { int num_threads = 4; int thread; int num_iters = 300; int num_done = 0; a_thread_data *thread_data; thread_data = (a_thread_data *)malloc( sizeof( a_thread_data ) * num_threads ); for( thread = 0; thread < num_threads; thread++ ) { thread_data[ thread ].num_iters = num_iters; thread_data[ thread ].thread = thread; thread_data[ thread ].done = FALSE; if( _beginthread( do_one_iter, 8096, (void *)&thread_data[thread] ) <= 0 ) { printf( "FAILED creating thread.\n" ); return( 1 ); } } while( num_done != num_threads ) { Sleep( 1000 ); num_done = 0; for( thread = 0; thread < num_threads; thread++ ) { if( thread_data[ thread ].done == TRUE ) { num_done++; } } } return( 0 ); } |
Discuss this page in DocCommentXchange. Send feedback about this page using email. |
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |