Skip to content

Instantly share code, notes, and snippets.

@ccw
Created March 27, 2012 15:41
Show Gist options
  • Save ccw/2217203 to your computer and use it in GitHub Desktop.
Save ccw/2217203 to your computer and use it in GitHub Desktop.
[C] Example of pthread_cond_timedwait_relative_np in OS X
#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