Reference <<proc*c/c++ precompiler Programmer ' s guide>> release 8.1.6---multithreaded The example in the applications chapter is a simple multithreaded program that seems to be aimed at the Linux environment, Requires Pthread.h or Thread.h two header files, but my computer's Linux environment does not have Oracle installed, so I modeled the example in the book with VC tools to write a simple multithreaded example (Windows multithreading function seems to be different from the use of the Linux multithreaded function is very big In fact, there are a lot of places that do not understand, and now do not feel the efficiency and concurrency problems. The code is as follows:
/*
* NAME:PROC_MUL.PC
* Pre-compiling condition: mode=oracle parse=full
* Use multiple threads to update records in the table; each thread has a separate context environment
* Table structure: CREATE table accounts (account number (), balance (36,2))
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlca.h>
#include <windows.h>
#define CONNINFO "Test/test"
#define THREADS 3
DWORD WINAPI Do_transaction (); Handling Transactions
void Get_transaction (); Get Records
void logon ();
void Logoff ();
void Err_report (); Error handling
/*
* Document the structure of the thread ID and run-time context
*/
struct parameters
{
Sql_context *ctx;
int thread_id;
};
typedef struct parameters parameters;
struct Record_log
{
char action; Type of action
unsigned int from_account; Out of account
unsigned int to_account; Enter account
float amount; Transfer amount
};
typedef struct RECORD_LOG Record_log;
/** data records to be updated **/
Record_log records[] = {
{' M ', 10001,10008,10},
{' M ', 10002,10008,10},
{' M ', 10003,10008,10},
{' M ', 10004,10008,10},
{' M ', 10005,10008,10},
{' M ', 10006,10008,10},
{' M ', 10007,10008,10},
{' M ', 10001,10008,10},
{' M ', 10002,10008,10}
};
static unsigned int trx_nr = 0;
static unsigned int flag_over = 0;
HANDLE Hmutex; Defining Mutex objects
/******** Main function *************/
void Main ()
{
Sql_context Ctx[threads];
HANDLE Thread_id[threads];
int status;
Parameters Params[threads];
int i;
/********* supports multithreading *********/
EXEC SQL ENABLE THREADS;
EXEC SQL whenever SQLERROR do Err_report (SQLCA);
/*create THEAD Sessions by connect THREAD times*/
for (i = 0; i < THREADS; i++)
{
printf ("Start session%d.../n", I);
EXEC SQL context Allocate:ctx[i]; Allocates and initializes a piece of memory that is used to point to a new Run-time context
Logon (Ctx[i], conninfo);
}
/* Create mutually exclusive objects * *
Hmutex = CreateMutex (NULL, FALSE, "Trx_nr");
if (Hmutex)
{
if (Error_already_exists==getlasterror ())
{
printf ("Only one instance can run ...");
Return
}
}
/* Create thread/*
for (i = 0; i < THREADS; i++)
{
Params[i].ctx = Ctx[i];
params[i].thread_id = i;
Thread_id[i] = CreateThread (NULL, 0, Do_transaction, ¶ms[i], 0, &thread_id[i]);
CloseHandle (Thread_id[i]);
}
/****** uses a global variable to determine whether all threads end ********/
while (Flag_over!= THREADS)
{
Sleep (10000);
}
/*************** have problems. ***************
Shutting down threads and database connections
for (i = 0; i < THREADS; i++)
{
if (WaitForSingleObject (thread_id[i],0) ==wait_object_0)
{
printf ("Test%d terminated/n", i);
printf ("Stop session%d.../n", I);
Logoff (Ctx[i]);
EXEC SQL context Free:ctx[i];
}
}
**************************************/
}
/*
* Data processing function, one record in recors[]
* recors[] records are managed through the get_transaction () function
*/
DWORD WINAPI do_transaction (Parameters *params)
{
struct SQLCA Sqlca; Local communication Area
Record_log *trx;
Sql_context CTX = params->ctx;
/* Process data, loop, know records[] all the data is processed.
while (Trx_nr < sizeof (records)/sizeof (Record_log))
{
WaitForSingleObject (Hmutex,infinite);
Get_transaction (&TRX); Get a record, need to use the address of the pointer
printf ("Thread%d is executing transaction.../n", params->thread_id);
ReleaseMutex (Hmutex);
EXEC SQL whenever SQLERROR do Err_report (SQLCA);
EXEC SQL context Use:ctx; Each thread has a separate context environment
Switch (trx->action)
{
Case ' M ':
EXEC SQL UPDATE account SET balance=balance+:trx->amount WHERE account=:trx->to_account;
EXEC SQL UPDATE account SET balance=balance-:trx->amount WHERE account=:trx->from_account;
Break
Default
Break
}
EXEC SQL COMMIT; Transaction submission
Sleep (2000);
}
/* thread end, close the database connection * *
printf ("Transaction finished, thread%d terminated/n", params->thread_id);
printf ("Stop Session%d.../n", params->thread_id);
Logoff (CTX);
EXEC SQL context Free:ctx; Free memory
flag_over++;
return 0;
}
/*
* Manage recors[] records, control concurrency
*/
void Get_transaction (Record_log **trx)
{
*trx = &records[trx_nr]; Get the record you are currently working on
trx_nr++;
}
/*
* Connect to the database
*/
void logon (Sql_context ctx, char *connect_info)
{
EXEC SQL whenever SQLERROR do Err_report (SQLCA);
EXEC SQL context Use:ctx;
EXEC SQL Connect:connect_info;
printf ("connect.../n");
}
/*
* Disconnect the database
*/
void Logoff (Sql_context ctx)
{
EXEC SQL whenever SQLERROR do Err_report (SQLCA);
EXEC SQL context Use:ctx;
EXEC SQL COMMIT WORK release;
printf ("Logged off/n");
}
/*
* Error handling function
*/
void Err_report (struct SQLCA sqlca)
{
if (Sqlca.sqlcode < 0)
{
printf ("/n%.*s/n/n", SQLCA.SQLERRM.SQLERRML,SQLCA.SQLERRM.SQLERRMC);
Exit (1);
}
}
Debugging in the VC6.0 environment is no problem, the results are normal. However, the output of the console is rather strange, sometimes messy, it seems that the implementation of the printf function when the writing problem, check for a long time do not know why.