Follow up of
previous post, try to simulate the
sigtimedwait method due to the fact that the method is lacked in OS X.
BTW,
ldd is also not found, just use
otool -L for an alternative.
#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);
}