|
|
@@ -23,7 +23,6 @@ |
|
|
|
#include <assert.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <pthread.h> |
|
|
|
#include <semaphore.h> |
|
|
|
#include <stdbool.h> |
|
|
|
#include <stdint.h> |
|
|
|
#include <stdlib.h> |
|
|
@@ -39,9 +38,12 @@ |
|
|
|
|
|
|
|
// my_mutex: protects my_thread_is_talking, |
|
|
|
static pthread_mutex_t my_mutex; |
|
|
|
static sem_t my_sem_start_is_required; |
|
|
|
static sem_t my_sem_stop_is_required; |
|
|
|
static sem_t my_sem_stop_is_acknowledged; |
|
|
|
static pthread_cond_t my_cond_start_is_required; |
|
|
|
static int my_start_is_required = 0; |
|
|
|
static pthread_cond_t my_cond_stop_is_required; |
|
|
|
static int my_stop_is_required = 0; |
|
|
|
static pthread_cond_t my_cond_stop_is_acknowledged; |
|
|
|
static int my_stop_is_acknowledged = 0; |
|
|
|
// my_thread: polls the audio duration and compares it to the duration of the first event. |
|
|
|
static pthread_t my_thread; |
|
|
|
static bool thread_inited; |
|
|
@@ -81,9 +83,9 @@ void event_init(void) |
|
|
|
pthread_mutex_init(&my_mutex, (const pthread_mutexattr_t *)NULL); |
|
|
|
init(); |
|
|
|
|
|
|
|
assert(-1 != sem_init(&my_sem_start_is_required, 0, 0)); |
|
|
|
assert(-1 != sem_init(&my_sem_stop_is_required, 0, 0)); |
|
|
|
assert(-1 != sem_init(&my_sem_stop_is_acknowledged, 0, 0)); |
|
|
|
assert(-1 != pthread_cond_init(&my_cond_start_is_required, NULL)); |
|
|
|
assert(-1 != pthread_cond_init(&my_cond_stop_is_required, NULL)); |
|
|
|
assert(-1 != pthread_cond_init(&my_cond_stop_is_acknowledged, NULL)); |
|
|
|
|
|
|
|
pthread_attr_t a_attrib; |
|
|
|
|
|
|
@@ -203,7 +205,7 @@ espeak_ng_STATUS event_declare(espeak_EVENT *event) |
|
|
|
|
|
|
|
espeak_ng_STATUS status; |
|
|
|
if ((status = pthread_mutex_lock(&my_mutex)) != ENS_OK) { |
|
|
|
sem_post(&my_sem_start_is_required); |
|
|
|
my_start_is_required = 1; |
|
|
|
return status; |
|
|
|
} |
|
|
|
|
|
|
@@ -211,10 +213,12 @@ espeak_ng_STATUS event_declare(espeak_EVENT *event) |
|
|
|
if ((status = push(a_event)) != ENS_OK) { |
|
|
|
event_delete(a_event); |
|
|
|
pthread_mutex_unlock(&my_mutex); |
|
|
|
} else |
|
|
|
} else { |
|
|
|
my_start_is_required = 1; |
|
|
|
pthread_cond_signal(&my_cond_start_is_required); |
|
|
|
status = pthread_mutex_unlock(&my_mutex); |
|
|
|
} |
|
|
|
|
|
|
|
sem_post(&my_sem_start_is_required); |
|
|
|
|
|
|
|
return status; |
|
|
|
} |
|
|
@@ -227,7 +231,8 @@ espeak_ng_STATUS event_clear_all() |
|
|
|
|
|
|
|
int a_event_is_running = 0; |
|
|
|
if (my_event_is_running) { |
|
|
|
sem_post(&my_sem_stop_is_required); |
|
|
|
my_stop_is_required = 1; |
|
|
|
pthread_cond_signal(&my_cond_stop_is_required); |
|
|
|
a_event_is_running = 1; |
|
|
|
} else |
|
|
|
init(); // clear pending events |
|
|
@@ -236,7 +241,8 @@ espeak_ng_STATUS event_clear_all() |
|
|
|
return status; |
|
|
|
|
|
|
|
if (a_event_is_running) { |
|
|
|
while ((sem_wait(&my_sem_stop_is_acknowledged) == -1) && errno == EINTR) |
|
|
|
while(my_stop_is_acknowledged == 0) |
|
|
|
while((pthread_cond_wait(&my_cond_stop_is_acknowledged, &my_mutex) == -1) && errno == EINTR) |
|
|
|
continue; // Restart when interrupted by handler |
|
|
|
} |
|
|
|
|
|
|
@@ -252,27 +258,19 @@ static void *polling_thread(void *p) |
|
|
|
|
|
|
|
int a_status = pthread_mutex_lock(&my_mutex); |
|
|
|
my_event_is_running = 0; |
|
|
|
pthread_mutex_unlock(&my_mutex); |
|
|
|
|
|
|
|
while ((sem_wait(&my_sem_start_is_required) == -1) && errno == EINTR) |
|
|
|
while(my_start_is_required == 0) |
|
|
|
while((pthread_cond_wait(&my_cond_start_is_required, &my_mutex) == -1) && errno == EINTR) |
|
|
|
continue; // Restart when interrupted by handler |
|
|
|
|
|
|
|
a_status = pthread_mutex_lock(&my_mutex); |
|
|
|
my_event_is_running = 1; |
|
|
|
pthread_mutex_unlock(&my_mutex); |
|
|
|
|
|
|
|
a_stop_is_required = 0; |
|
|
|
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); // NOTE: may set a_stop_is_required to -1 |
|
|
|
if ((a_status == 0) && (a_stop_is_required > 0)) { |
|
|
|
while (0 == sem_trywait(&my_sem_stop_is_required)) |
|
|
|
; |
|
|
|
} else |
|
|
|
a_stop_is_required = 0; |
|
|
|
my_start_is_required = 0; |
|
|
|
|
|
|
|
pthread_mutex_unlock(&my_mutex); |
|
|
|
|
|
|
|
// In this loop, my_event_is_running = 1 |
|
|
|
while (head && (a_stop_is_required <= 0)) { |
|
|
|
while (0 == sem_trywait(&my_sem_start_is_required)) |
|
|
|
; |
|
|
|
while (head && (a_stop_is_required == 0)) { |
|
|
|
|
|
|
|
espeak_EVENT *event = (espeak_EVENT *)(head->data); |
|
|
|
assert(event); |
|
|
@@ -287,40 +285,35 @@ static void *polling_thread(void *p) |
|
|
|
|
|
|
|
a_status = pthread_mutex_lock(&my_mutex); |
|
|
|
event_delete((espeak_EVENT *)pop()); |
|
|
|
a_status = pthread_mutex_unlock(&my_mutex); |
|
|
|
a_stop_is_required = my_stop_is_required; |
|
|
|
if(a_stop_is_required > 0) |
|
|
|
my_stop_is_required = 0; |
|
|
|
|
|
|
|
a_stop_is_required = 0; |
|
|
|
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); |
|
|
|
|
|
|
|
if ((a_status == 0) && (a_stop_is_required > 0)) { |
|
|
|
while (0 == sem_trywait(&my_sem_stop_is_required)) |
|
|
|
; |
|
|
|
} else |
|
|
|
a_stop_is_required = 0; |
|
|
|
a_status = pthread_mutex_unlock(&my_mutex); |
|
|
|
} |
|
|
|
|
|
|
|
a_status = pthread_mutex_lock(&my_mutex); |
|
|
|
|
|
|
|
my_event_is_running = 0; |
|
|
|
|
|
|
|
if (a_stop_is_required <= 0) { |
|
|
|
a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); |
|
|
|
if ((a_status == 0) && (a_stop_is_required > 0)) { |
|
|
|
while (0 == sem_trywait(&my_sem_stop_is_required)) |
|
|
|
; |
|
|
|
} else |
|
|
|
a_stop_is_required = 0; |
|
|
|
if (a_stop_is_required == 0) { |
|
|
|
a_stop_is_required = my_stop_is_required; |
|
|
|
if (a_stop_is_required > 0) |
|
|
|
my_stop_is_required = 0; |
|
|
|
} |
|
|
|
|
|
|
|
a_status = pthread_mutex_unlock(&my_mutex); |
|
|
|
|
|
|
|
if (a_stop_is_required > 0) { |
|
|
|
// no mutex required since the stop command is synchronous |
|
|
|
// and waiting for my_sem_stop_is_acknowledged |
|
|
|
// and waiting for my_cond_stop_is_acknowledged |
|
|
|
init(); |
|
|
|
|
|
|
|
// acknowledge the stop request |
|
|
|
a_status = sem_post(&my_sem_stop_is_acknowledged); |
|
|
|
espeak_ng_STATUS a_status = pthread_mutex_lock(&my_mutex); |
|
|
|
my_stop_is_acknowledged = 1; |
|
|
|
a_status = pthread_cond_signal(&my_cond_stop_is_acknowledged); |
|
|
|
a_status = pthread_mutex_unlock(&my_mutex); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -394,9 +387,9 @@ void event_terminate() |
|
|
|
pthread_cancel(my_thread); |
|
|
|
pthread_join(my_thread, NULL); |
|
|
|
pthread_mutex_destroy(&my_mutex); |
|
|
|
sem_destroy(&my_sem_start_is_required); |
|
|
|
sem_destroy(&my_sem_stop_is_required); |
|
|
|
sem_destroy(&my_sem_stop_is_acknowledged); |
|
|
|
pthread_cond_destroy(&my_cond_start_is_required); |
|
|
|
pthread_cond_destroy(&my_cond_stop_is_required); |
|
|
|
pthread_cond_destroy(&my_cond_stop_is_acknowledged); |
|
|
|
init(); // purge event |
|
|
|
thread_inited = 0; |
|
|
|
} |