Created
March 27, 2012 15:41
-
-
Save ccw/2217203 to your computer and use it in GitHub Desktop.
[C] Example of pthread_cond_timedwait_relative_np in OS X
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <pthread.h> | |
#include <errno.h> | |
#include <unistd.h> | |
#include <time.h> | |
#include <signal.h> | |
#define SIG_A (SIGUSR2 - 0) | |
#define SIG_B (SIGUSR2 - 1) | |
#define SIG_C (SIGQUIT) | |
#define S 1 | |
#define F 0 | |
#define TIMES 10 | |
/* | |
* data structure | |
*/ | |
typedef struct _proc { | |
char name[2]; | |
int data; | |
pthread_t thread; | |
pthread_mutex_t lock; | |
pthread_cond_t cond; | |
long int waits; | |
sigset_t sigset; | |
} PROC; | |
/* | |
* variables | |
*/ | |
static PROC *listener; | |
/* | |
* methods | |
*/ | |
void _exec_and_wait(void* args) { | |
PROC *proc = (PROC*) args; | |
static struct timespec time_to_wait = {0, 0}; | |
// signal version | |
int recSignal; | |
while(proc->data < 999) { | |
if (0 == sigwait(&proc->sigset, &recSignal)) { | |
pthread_mutex_lock(&proc->lock); | |
switch (recSignal) { | |
case SIG_A: | |
printf("proc[%s] receive SIG_A\n", proc->name); | |
proc->data++; | |
break; | |
case SIG_B: | |
printf("proc[%s] receive SIG_B\n", proc->name); | |
proc->data += 5; | |
break; | |
case SIG_C: | |
printf("proc[%s] receive SIG_C\n", proc->name); | |
proc->data += 999; | |
break; | |
default: | |
printf("proc[%s] receive unknow signal [%d]\n", proc->name, recSignal); | |
} | |
pthread_mutex_unlock(&proc->lock); | |
} else { | |
printf("proc[%s] fail to receive signal [%d]\n", proc->name); | |
} | |
} | |
printf("proc[%s] finished\n", proc->name); | |
} | |
void _exec_to_signal(void* args) { | |
PROC *proc = (PROC*) args; | |
static struct timespec time_to_wait = {0, 0}; | |
int sig_sending; | |
if (listener != NULL) { | |
srand(time(NULL)); | |
time_to_wait.tv_sec = proc->waits; | |
while(proc->data < TIMES) { | |
pthread_mutex_lock(&proc->lock); | |
pthread_cond_timedwait_relative_np(&proc->cond, &proc->lock, &time_to_wait); | |
sig_sending = (rand() % 2 > 0) ? SIG_A : SIG_B; | |
printf("proc[%s] is sending signal[%d]\n", proc->name, sig_sending); | |
pthread_kill(listener->thread, sig_sending); | |
proc->data++; | |
pthread_mutex_unlock(&proc->lock); | |
} | |
printf("proc[%s] is sending signal[%d]\n", proc->name, SIG_C); | |
pthread_kill(listener->thread, SIG_C); // to terminate listener | |
} else { | |
printf("proc[%s] is aborting signal[%d], due to no listener registered\n", proc->name, SIG_A); | |
} | |
printf("proc[%s] finished\n", proc->name); | |
} | |
int _init_proc(PROC *proc, void *(*routine) (void *)) { | |
pthread_attr_t attr; | |
// | |
printf("try to init proc [%s]\n", proc->name); | |
pthread_attr_init(&attr); | |
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | |
// | |
pthread_mutex_init(&proc->lock, NULL); | |
pthread_cond_init(&proc->cond, NULL); | |
// | |
pthread_create(&proc->thread, &attr, routine, (void*) proc); | |
pthread_attr_destroy(&attr); | |
// | |
return S; | |
} | |
int _init_signal_proc(PROC *proc, void *(*routine) (void *)) { | |
pthread_attr_t attr; | |
// | |
printf("try to init proc [%s]\n", proc->name); | |
// | |
sigemptyset(&proc->sigset); | |
sigaddset(&proc->sigset, SIG_A); | |
sigaddset(&proc->sigset, SIG_B); | |
sigaddset(&proc->sigset, SIG_C); | |
pthread_sigmask(SIG_BLOCK, &(proc->sigset), NULL); | |
// | |
pthread_attr_init(&attr); | |
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | |
// | |
pthread_mutex_init(&proc->lock, NULL); | |
// | |
pthread_create(&proc->thread, &attr, routine, (void*) proc); | |
pthread_attr_destroy(&attr); | |
// | |
return S; | |
} | |
/* | |
* main | |
*/ | |
int main(int argc, char** argv) | |
{ | |
int result_a = 0, result_b = 0; | |
PROC proc_a, proc_b; | |
strcpy(proc_a.name, "A\0"); | |
proc_a.data = 0; | |
proc_a.waits = 1L; | |
strcpy(proc_b.name, "B\0"); | |
proc_b.data = 0; | |
proc_b.waits = 800L; | |
listener = &proc_b; | |
if (!_init_proc(&proc_a, _exec_to_signal)) | |
printf("Fail to init proc [%s]\n", proc_a.name); | |
/* */ | |
if (!_init_signal_proc(&proc_b, _exec_and_wait)) | |
printf("Fail to init proc [%s]\n", proc_b.name); | |
/* */ | |
pthread_join(proc_a.thread, (void*) &result_a); | |
pthread_join(proc_b.thread, (void*) &result_b); | |
return (EXIT_SUCCESS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment