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

📄 cancel.c

📁 linux下多线程程序设计,包括signals,mutex,simple_once
💻 C
字号:
/********************************************************
 * An example source module to accompany...
 *
 * "Using POSIX Threads: Programming with Pthreads"
 *     by Brad nichols, Dick Buttlar, Jackie Farrell
 *     O'Reilly & Associates, Inc.
 *
 ********************************************************
 * cancel.c --
 *
 * Demonstrates pthread cancellation.
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

#include <pthread.h>

#define NUM_THREADS  2
#define MESSAGE_MAX_LEN 80

int               count=NUM_THREADS;    /* number of threads active */
pthread_mutex_t   lock=PTHREAD_MUTEX_INITIALIZER; /* mutual exclusion 
						     for count */
pthread_cond_t    init_done=PTHREAD_COND_INITIALIZER; /* signaled by 
							 each thread after
							 completing initial-
							 ization */
int id_arg[3] = {0,1,2};

/*
 * Cleanup routine: last_breath()
 */
void last_breath(char *messagep)
{  
	printf("\n\n%s last_breath() cleanup routine: free'ing 0x%x\n\n", messagep, messagep);
	
	free(messagep);
}

/*
 * print_count()
 */
void print_count(char *messagep, int id, int i)
{
	int last_type,tmp_type;
	
	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_type);
	switch(id) 
	{
		case 0:
			printf("%s %4d\n", messagep, i);
			break;
		case 1:
			printf("%s \t%4d\n", messagep, i);
			break;
		case 2:
			printf("%s \t\t%4d\n", messagep, i);
			break;
	}
	pthread_setcanceltype(last_type, &tmp_type);
}

/*
 * bullet_proof()
 */
void *bullet_proof(void *id_p)
{
	int i = 0, last_state;
	int *my_id = id_p;
	char *messagep;
	
	
	messagep = (char *)malloc(MESSAGE_MAX_LEN);
	sprintf(messagep, "Bullet Proof, thread #%d: ", *my_id);
	
	printf("%s\tI'm Alive, setting general cancellation OFF\n", messagep);
	
	/* push last_breath() routine onto stack */
	#if defined(__digital__) && defined(__unix__)
	pthread_cleanup_push(last_breath, (void *)messagep );
	#else /* GCC/Linux  */
	pthread_cleanup_push( (void *)last_breath, (void *)messagep );
	#endif
	
	/* We turn off general cancelability here ... */
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &last_state);
	
	pthread_mutex_lock(&lock);
	{
		printf("\n%s signaling main that my init is done\n", messagep);
		count -= 1;
		/* signal to program that entering loop */
		pthread_cond_signal(&init_done);
		pthread_mutex_unlock(&lock);
	}
	
	/* loop forever until picked off with a cancel */
	for(;;i++) 
	{
		if (i%1000 == 0) 
			print_count(messagep, *my_id, i); 
		if (i%100000 == 0) 
			printf("\n%s This is the thread that never ends... #%d\n", messagep, i);
	}
	
	/* Never get this far   */
	
	/* This pop is required by the standard, every push must have a pop 
	in the same lexical block. */
	pthread_cleanup_pop(0);
	
	return(NULL);
}

/*
 * ask_for_it()
 */
void *ask_for_it(void *id_p)
{
	int i=0, last_state, last_type;
	int *my_id = id_p;
	char *messagep;
	
	
	messagep = (char *)malloc(MESSAGE_MAX_LEN);
	sprintf(messagep, "Ask For It, thread #%d: ", *my_id);
	
	/* push last_breath() routine onto stack */
	#if defined(__digital__) && defined(__unix__)
	pthread_cleanup_push(last_breath, (void *)messagep);
	#else /* GCC/Linux  */
	pthread_cleanup_push( (void *)last_breath, (void *)messagep);
	#endif
	
	
	/* We can turn on general cancelability here. Disable async cancellation */
	printf("%s\tI'm Alive, setting deferred cancellation ON\n", messagep);
	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_type);
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state);
	
	pthread_mutex_lock(&lock);
	{
		printf("\n%s signaling main that my init is done\n", messagep);
		count -= 1;
		/* signal to program that entering loop */
		pthread_cond_signal(&init_done);
		pthread_mutex_unlock(&lock);
	}
	
	/* loop forever until picked off with a cancel */
	for(;;i++) 
	{
		if (i%1000 == 0)
			print_count(messagep, *my_id, i);
		if (i%10000 == 0) 
			printf("\n%s\tLook, I'll tell you when you can cancel me.\n",messagep,i);
		pthread_testcancel();
	}
	
	/* never get this far */
	
	/* This pop is required by the standard, every push must have a pop 
	in the same lexical block. */
	pthread_cleanup_pop(0);
	
	return(NULL);
}

/*
 * sitting_duck()
 */
void *sitting_duck(void *id_p)
{
	int i=0, last_state, last_type, last_tmp;
	int *my_id = id_p;
	char *messagep;
	
	
	messagep = (char *)malloc(MESSAGE_MAX_LEN);
	sprintf(messagep, "Sitting Duck, thread #%d: ", *my_id);
	
	/* push last_breath() routine onto stack */
	#if defined(__digital__) && defined(__unix__)
	pthread_cleanup_push(last_breath, (void *)messagep);
	#else /* GCC/Linux  */
	pthread_cleanup_push( (void *)last_breath, (void *)messagep);
	#endif
	
	pthread_mutex_lock(&lock);
	{
		printf("\n%s signaling main that my init is done\n", messagep);
		count -= 1;
		/* signal to program that entering loop */
		pthread_cond_signal(&init_done);
		pthread_mutex_unlock(&lock);
	}
	
	/* Now, we're safe to turn on async cancellability */
	printf("%s\tI'm Alive, setting async cancellation ON\n", messagep);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_type);
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &last_state);
	
	/* loop forever until picked off with a cancel */
	for(;;i++) 
	{
		if (i%1000 == 0) 
			print_count(messagep, *my_id, i++);
		if (i%10000 == 0) 
		{
			pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &last_tmp);
			printf("\n%s\tHum, nobody here but us chickens. %d\n", messagep,i);
			pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &last_tmp);
		}
	}
	
	/* never get this far */
	
	/* This pop is required by the standard, every push must have a pop 
	in the same lexical block. */
	pthread_cleanup_pop(0);
	
	return(NULL);
}

extern int 	main(void)
{
	int       i;
	void *statusp;
	pthread_t threads[NUM_THREADS];
	
	
	/* spawn the threads */
	pthread_create(&(threads[0]), NULL,  ask_for_it, (void *) &(id_arg[0]));
	pthread_create(&(threads[1]), NULL,  sitting_duck,  (void *) &(id_arg[1]));	
	pthread_create(&(threads[2]), NULL,  bullet_proof, (void *) &(id_arg[2]));
	printf("main(): %d threads created\n", NUM_THREADS);
	
	pthread_mutex_lock(&lock);
	
	/* wait until all threads have entered loops */
	while (count != 0) 
	{
		pthread_cond_wait(&init_done, &lock);
	}
	
	pthread_mutex_unlock(&lock);
	printf("main(): all threads have signaled that ready\n");

	/* cancel each thread */
	for (i=0; i<NUM_THREADS; i++) 
	{
		pthread_cancel(threads[i]);
	}
	
	/* wait until all threads have finished */
	for (i=0; i<NUM_THREADS; i++) 
	{
		pthread_join(threads[i], &statusp);
		if (statusp == PTHREAD_CANCELED) 
		{
			printf("main(): joined to thread %d, statusp=PTHREAD_CANCELED\n",i);
		} 
		else 
		{
			printf("main(): joined to thread %d\n",i);
		}
	}
	
	printf("main()\t\tall %d threads have finished. \n", NUM_THREADS);
	
	return 0;
}

⌨️ 快捷键说明

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