⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 multthrd.c

📁 sybase数据库ct library的开发,使用了所以有函数
💻 C
📖 第 1 页 / 共 2 页
字号:


/*
**
** Description
** -----------
**	This example demonstrates using Client library from multiple 
**	application threads. It spawns 5 threads.  Each thread processes 
**	a cursor or a regular query. The application main thread waits for 
**	the other threads to complete query processing and terminate. 
**	
**	This sample follows a one-thread, one-connection model. In this model,
**	the program performs all needed library initialization and cleanup
**	in single threaded initialization and cleanup code. In this program,
**	it is performed in application main thread. It creates a dedicated
**	thread for each connection and limits all use of a particular
**	connection to its dedicated thread. This model is the simplest
**	and requires the least amount of inter-thread synchronization.
**
**      The basic steps followed in this sample are,	
**
**	o	All thread-unsafe library/context initialization calls
**		are made from the application main thread. 
**	 
** 	o	After the initialization has been performed, the main thread 
**		spawns one thread for each connection to be created. The 
**		thread then allocates its own connection with ct_con_alloc, 
**		connects to the server, and performs processing for that
**		connection. 
**
**	o	After spawning the threads, the application main thread waits 
**		for the threads to terminate. When the threads complete 
**		processing the query, each thread closes its own connection 
**		and terminates itself. Before terminating, it also signals the 
**	 	main thread. The application main thread then performs the 
**		necessary cleanup in the process limiting thread unsafe calls 
**		to a single thread, itself. 
**
**	Synchronization/serialization, and thread/connection specific data:
**
**	o	Thread number is stored as user data in the connection/context
**		associated with that thread. This is useful since it
**		may be retrieved in callbacks or other places where it
**		may be needed to notify the user about the connection 
**		that resulted in a error message. An alternative would be to
**		use thread-specific data primitives provided by the OS thread  
**		layer. However, this alternative cannot be used when
**		callbacks are called in the context of a client library internal
**		thread (this happens when async property is set to
**		full async mode).  
**
**	o	A semaphore is used to notify the application main thread
**		about termination of the query threads.
**
**	o	A global mutex is used to protect usage of a shared resource
**		- printing to stdout/stderr - This is really not essential
**		for this sample to work. It is merely used to avoid output 
**		from different threads from being garbled.
**		  
**
**	Cursor query thread: 
**	This thread demonstrates using a read-only cursor.  It opens a cursor
**	with a canned query.  It processes the results using the standard
**	ct_results() while loop.  It binds the column values to program
**	variables.  It then fetches and displays the rows in the standard
**	ct_fetch() while loop.                                          
**
**	Regular query thread:
**	This demonstrates processing a regular query. It sends a canned
**	query to the server and processes the results using the standard
**	ct_results() while loop. It binds the column values to program
**	variables using array binding. It then fetches and displays the
**	result rows in the standard ct_fetch() while loop.
**
**	Canned queries:
**		select au_fname, au_lname, postalcode from authors
**		select * from sysobjects
**		select * from stores, titles
**
**
** Routines Used
** -------------
**	cs_ctx_alloc()
**	ct_init()
**	ct_config()
**	ct_callback()
**	ct_con_alloc()
**	ct_con_props()
**	ct_connect()
**	ct_cmd_alloc()
**	ct_cursor(CS_CURSOR_DECLARE)
**	ct_cursor(CS_CURSOR_ROWS)
**	ct_cursor(CS_CURSOR_OPEN)
**	ct_cursor(CS_CURSOR_CLOSE)
**	ct_send()
**	ct_results()
**	ct_res_info()
**	ct_describe()
**	ct_bind()
**	ct_fetch()
**	ct_cmd_drop()
**	ct_close()
**	ct_con_drop()
**	ct_exit()
**	ct_ctx_drop()
**
**
** Input
** -----
**	This example uses hard-coded queries of the authors, stores and titles
**	tables in the pubs2 database. One of the query uses the server
**	system table sysobjects. 
**
**
** Output
** ------
**	This example simply displays each row of the result set. Output
**	from different threads will be interleaved. Each line of output
**	specifies the thread from which it was generated. 
**
**
** Server Dependencies
** -------------------
**	This example requires a 10.0 or higher SQL Server.
**
**
** Server Tables
** -------------
**	This example relies on the pubs2 database - authors, stores and
**	titles tables and the server system table sysobjects.
**
**
** Other Requirements
** ------------------
**	This sample requires a thread package to be available for the build
**	and execution. Not all platforms support a thread package. Please read 
**	the readme file associated with the samples and the platform supplement 
**	for Open Client for information on the thread packages that are 
**	supported. If no thread package is available on a platform, this
**	sample is not supported. 
**
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctpublic.h>
#include "example.h"
#include "thrdutil.h"
#include "thrdfunc.h"

/*****************************************************************************
** 
** defines and globals used.
** 
*****************************************************************************/

/*
** Define  sample select statements
*/
#define QUERY1	"select au_fname, au_lname, postalcode from authors"
#define QUERY2	"select * from sysobjects"
#define QUERY3	"select * from stores, titles"

#define PUBS2_DB "pubs2"
#define MASTER_DB "master"

#define EX_MAX_THREADS 5

/*
** Global names used in this module
*/
CS_CHAR *Ex_appname  = "Multithreaded_sample";
CS_CHAR *Ex_server   = EX_SERVER;
CS_CHAR *Ex_username = EX_USERNAME;
CS_CHAR *Ex_password = EX_PASSWORD;

/* Other globals */

/* task list */
CS_STATIC EX_TASK Ex_tasks[] =
{
	{NULL, NULL, NULL, QUERY1, PUBS2_DB, EX_CURSOR_QUERY}, 
	{NULL, NULL, NULL, QUERY2, MASTER_DB, EX_REGULAR_QUERY},  
	{NULL, NULL, NULL, QUERY1, PUBS2_DB, EX_CURSOR_QUERY},
	{NULL, NULL, NULL, QUERY2, MASTER_DB,  EX_CURSOR_QUERY}, 
	{NULL, NULL, NULL, QUERY3, PUBS2_DB, EX_REGULAR_QUERY}, 
};
 
/*
** Semaphore for synchronizing thread completions
*/
CS_STATIC CS_VOID *Ex_threadcompsem;


/*
** Prototypes for routines 
*/
CS_STATIC CS_RETCODE DoCursor PROTOTYPE((
	CS_CONNECTION *connection,
	EX_TASK *task
	));
CS_STATIC CS_RETCODE DoQuery PROTOTYPE((
	CS_CONNECTION *connection,
	EX_TASK *task
	));
CS_STATIC CS_RETCODE SendCmdAndCheckResults PROTOTYPE((
	CS_INT		threadnum,
	CS_COMMAND 	*cmd,
	CS_INT	   	restype
	));

CS_RETCODE thread_main PROTOTYPE((
	EX_TASK	*task
	));

/*
** main()
** 
** Purpose:
**	Entry point for the multithreaded example program. 
**	It does the following:
**		Sets up a global mutex mechanism.
**		Creates a synchronization semaphore for reporting thread
**			completions.
**		Allocates and initializes a cs context structure.
**		Sets up the thread task structures and spawns the threads
**			to perform these tasks.
**		Waits for the threads to terminate.
**		Performs the cleanup of all the resources.
** 
** Parameters:
**	None, argc and argv will not be used.
**
** Return:
** 	EX_EXIT_ERROR  or EX_EXIT_SUCCEED
**
*/

int
main()
{
	CS_CONTEXT	*context;
	CS_RETCODE	retcode;
	CS_INT		threadnum;
	CS_INT		i;
	CS_INT		threadcount;

	EX_SCREEN_INIT();

	threadnum = 0;
	threadcount = 0;
	
	fprintf(stdout, "Multithreaded Example\n");
	fflush(stdout);

	/*
	** Initialize global mutex mechanism
	*/
	if (ex_create_global_mutex() != CS_SUCCEED)
	{
		/* panic */
		fprintf(stdout, "ex_init_global_mutex() failed\n");
		exit(EX_EXIT_FAIL);
	}

	/*
	** Create a semaphore to be used later to
	** synchronize completion of threads 
	*/
	retcode = ex_create_sem(&Ex_threadcompsem, EX_MAX_THREADS);
	if (retcode != CS_SUCCEED)
	{
		ex_panic(threadnum, "ex_create_sem failed");
	}

	/* 
	** Allocate a context structure and initialize Client-Library 
	*/
	retcode = ex_init(threadnum, &context);
	if (retcode != CS_SUCCEED)
	{
		(void)ex_delete_sem(Ex_threadcompsem);
		ex_panic(threadnum, "ex_init failed");
	}

	/* set context */
	for (i = 0; i < EX_MAX_THREADS; i++)
	{ 
		Ex_tasks[i].context = context; 
		Ex_tasks[i].threadnum = i + 1;
	}

	/*
	** Spawn threads to do the tasks 
	*/
	for (i = 0; i < EX_MAX_THREADS; i++)
	{ 
		if (ex_create_thread(&(Ex_tasks[i].thread), 
					(CS_VOID *)thread_main, 
					&Ex_tasks[i]) != CS_SUCCEED)
		{
			ex_error(threadnum, "ex_create_thread failed");
			break;
		} 
		threadcount++;
	}

	/*
	** Wait for the threads to complete
	*/
	while (threadcount > 0)
	{
		if (ex_waitfor_sem(Ex_threadcompsem) != CS_SUCCEED)
		{
			ex_panic(threadnum, "ex_waitfor_sem failed");
		}
		threadcount--;
	}

	/* cleanup */
	for (i = 0; i < EX_MAX_THREADS; i++)
	{ 
		(void)ex_detach_thread(Ex_tasks[i].thread);
	}

	if (context != NULL)
	{
		retcode = ex_ctx_cleanup(context, retcode);
	}

	(void)ex_delete_sem(Ex_threadcompsem);
	(void)ex_delete_global_mutex();

	return (retcode == CS_SUCCEED) ? EX_EXIT_SUCCEED : EX_EXIT_FAIL;
}


/*
** thread_main(task)
**
** Type of function:
**	Multithreaded sample - thread main routine.
**
** Purpose:
**	This is the thread main routine. When a thread is spawned 
**	with this as start routine, it creates a connection; performs the
**	operation specified in the task entry and cleans up the
**	connection before terminating itself.
**
** Parameters:
**      task - pointer to EX_TASK entry with sql query and db name
**
** Return:
**	CS_SUCCEED - if the task specified completed successfully
**	Otherwise a Client-Library failure code.
*/

CS_RETCODE
thread_main(task)
EX_TASK	*task;
{
        CS_CONNECTION   *connection;
        CS_RETCODE      retcode;

        /*
        ** Allocate a connection structure, set its properties, and
        ** establish a connection.
        */
        retcode = ex_connect(task->threadnum, task->context, &connection, 
				Ex_appname, Ex_username, Ex_password, 
				Ex_server);
 
        /*
        ** Execute the routine for processing the query 
        */
        if (retcode == CS_SUCCEED)
        {
		switch (task->operation)
		{
		 	case EX_CURSOR_QUERY:
                		retcode = DoCursor(connection, task);
				break;
			case EX_REGULAR_QUERY:
				retcode = DoQuery(connection, task);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -