2 Коммиты 9f36d1fb6a ... 1c49581afd

Автор SHA1 Сообщение Дата
  John Scott 1c49581afd Disable buffering on standard output 3 лет назад
  John Scott b0e9423636 Refactor thread_stop() to take care of (un)locking the mutex 3 лет назад
1 измененных файлов с 36 добавлено и 31 удалено
  1. 36 31
      wc.l

+ 36 - 31
wc.l

@@ -160,27 +160,21 @@ static void dfree(void *ptr) {
 	free(*(char**)ptr);
 }
 
-static void lock_mutex(void *mut) {
-	int k = pthread_mutex_lock(mut);
+static void thread_stop(void *index) {
+	int k = pthread_mutex_lock(&thread_is_running_guard);
 	if(k) {
 		fprintf(stderr, "Failed to lock mutex: %s\n", strerror(k));
 		abort();
 	}
-}
-
-static void unlock_mutex(void *mut) {
-	int k = pthread_mutex_unlock(mut);
+	assert(thread_is_running[*(const int*)index]);
+	thread_is_running[*(const int*)index] = false;
+	k = pthread_mutex_unlock(&thread_is_running_guard);
 	if(k) {
 		fprintf(stderr, "Failed to unlock mutex: %s\n", strerror(k));
 		abort();
 	}
 }
 
-static void thread_stop(void *index) {
-	assert(thread_is_running[*(const int*)index]);
-	thread_is_running[*(const int*)index] = false;
-}
-
 /* According to the command-line options, print the count of
  * what was found with an optional filename, which may be omitted. */
 static bool show_count(const struct count a[restrict static 1], const char *restrict filename) {
@@ -240,16 +234,23 @@ void *do_count(void *filename) {
 		abort();
 	}
 
+	int k = pthread_mutex_lock(&thread_is_running_guard);
+	if(k) {
+		fprintf(stderr, "Failed to lock mutex: %s\n", strerror(k));
+		abort();
+	}
+	assert(!thread_is_running[my_seq_thread_id]);
+	thread_is_running[my_seq_thread_id] = true;
+	k = pthread_mutex_unlock(&thread_is_running_guard);
+	if(k) {
+		fprintf(stderr, "Failed to unlock mutex: %s\n", strerror(k));
+		abort();
+	}
+
 	/* This has to be declared up here because we want c to
 	 * have scope outside of all of the pthread_cleanup_{push, pop} calls. */
 	struct count *c;
-
-	lock_mutex(&thread_is_running_guard);
-	thread_is_running[my_seq_thread_id] = true;
-	unlock_mutex(&thread_is_running_guard);
-	pthread_cleanup_push(unlock_mutex, &thread_is_running_guard);
 	pthread_cleanup_push(thread_stop, &my_seq_thread_id);
-	pthread_cleanup_push(lock_mutex, &thread_is_running_guard);
 
 	c = calloc(1, sizeof(*c));
 	if(!c) {
@@ -294,18 +295,13 @@ void *do_count(void *filename) {
 	}
 
 	yyset_in(stream, scanner);
-	if(yylex(scanner)) {
-		pthread_exit(NULL);
-	}
-	if(!show_count(c, filename)) {
+	if(yylex(scanner) || !show_count(c, filename)) {
 		pthread_exit(NULL);
 	}
 	pthread_cleanup_pop(true); /* destroy_file(stream) */
 	pthread_cleanup_pop(true); /* destroy_scanner(scanner) */
 	pthread_cleanup_pop(false); /* DO NOT free(c) */
-	pthread_cleanup_pop(true); /* lock thread_is_running_guard */
-	pthread_cleanup_pop(true); /* thread_is_running[my_seq_thread_id] = false */
-	pthread_cleanup_pop(true); /* unlock thread_is_running_guard */
+	pthread_cleanup_pop(true); /* thread_stop(&my_seq_thread_id) */
 	pthread_exit(c);
 }
 
@@ -351,6 +347,11 @@ int main(int argc, char *argv[]) {
 		 * when creating the child thread. */
 	}
 
+	if(setvbuf(stdout, NULL, _IONBF, 0)) {
+		fputs("Failed to disable buffering on standard output\n", stderr);
+		exit(EXIT_FAILURE);
+	}
+
 	/* To make cleanup easier, we do all of our dynamic memory
 	 * allocations before we get any threads started. */
 	pthread_t *ids = calloc(argc, sizeof(*ids));
@@ -454,14 +455,14 @@ tryagain:
 	if(argc >= 2) {
 		exit(show_count(&total, "total") ? EXIT_SUCCESS : EXIT_FAILURE);
 	}
-	if(fflush(stdout) == EOF) {
-		perror("Failed to flush standard output");
-		exit(EXIT_FAILURE);
-	}
 	exit(EXIT_SUCCESS);
 
 bail:
-	lock_mutex(&thread_is_running_guard);
+	k = pthread_mutex_lock(&thread_is_running_guard);
+	if(k) {
+		fprintf(stderr, "Failed to lock mutex: %s\n", strerror(k));
+		abort();
+	}
 	for(int i = 0; i < argc; i++) {
 		if(thread_is_running[i]) {
 			int k = pthread_cancel(ids[i]);
@@ -471,11 +472,15 @@ bail:
 			}
 		}
 	}
-	unlock_mutex(&thread_is_running_guard);
+	k = pthread_mutex_unlock(&thread_is_running_guard);
+	if(k) {
+		fprintf(stderr, "Failed to unlock mutex: %s\n", strerror(k));
+		abort();
+	}
 
 	void *retval;
 	for(int i = 0; i < argc; i++) {
-		int k = pthread_join(ids[i], &retval);
+		k = pthread_join(ids[i], &retval);
 		if(k) {
 			fprintf(stderr, "Failed to join with thread: %s\n", strerror(k));
 			abort();