Beispiel #1
0
void async_wait(struct async *self)
{
	int i;

	pthread_mutex_lock(&self->lock);
	self->shutdown = 1;
	pthread_mutex_unlock(&self->lock);

	pthread_cond_broadcast(&self->notify);

	for (i = 0; i < self->thread_num; i++)
		pthread_join(self->threads[i], NULL);
	async_destroy(self);
}
Beispiel #2
0
/**
 * \brief Waits for an Async object to finish up (joins all the threads
 *        in the thread pool) and DESTROYS the Async object (frees its
 *        memory and resources).
 *
 * This function will wait forever or until a signal is received and all
 * the tasks in the queue have been processed.
 */
static void async_wait(async_p async)
{
    if (!async) return;

    /* wake threads (just in case) by sending `async->count`
     * number of wakeups
     */
    if (async->pipe.out)
        write(async->pipe.out, async, async->count);
    /* join threads */
    for (int i = 0; i < async->count; i++) {
        join_thread(async->threads[i]);
    }
    /* perform any pending tasks */
    perform_tasks(async);
    /* release queue memory and resources */
    async_destroy(async);
}
Beispiel #3
0
int main(int const argc, char const *const *const argv) {
    // Depending on how async_pool and async_fs are configured, we might be
    // using our own thread pool heavily or not. However, at the minimum,
    // uv_getaddrinfo uses the libuv thread pool, and it blocks on the
    // network, so don't set this number too low.
    if(!getenv("UV_THREADPOOL_SIZE")) putenv((char *)"UV_THREADPOOL_SIZE=4");

    raiserlimit();
    async_init();

    int rc = tls_init();
    if(rc < 0) {
        alogf("TLS initialization error: %s\n", strerror(errno));
        return 1;
    }

    if(2 != argc || '-' == argv[1][0]) {
        alogf("Usage:\n\t" "%s repo\n", argv[0]);
        return 1;
    }
    path = argv[1];

    // Even our init code wants to use async I/O.
    async_spawn(STACK_DEFAULT, init, NULL);
    uv_run(async_loop, UV_RUN_DEFAULT);

    async_spawn(STACK_DEFAULT, term, NULL);
    uv_run(async_loop, UV_RUN_DEFAULT);

    // cleanup is separate from term because connections might
    // still be active.
    async_spawn(STACK_DEFAULT, cleanup, NULL);
    uv_run(async_loop, UV_RUN_DEFAULT);

    async_destroy();

    // TODO: Windows?
    if(sig) raise(sig);

    return 0;
}
Beispiel #4
0
int
main (
	int		argc,
	char*		argv[]
	)
{
	pgm_error_t* pgm_err = NULL;

	setlocale (LC_ALL, "");

#ifndef _WIN32
	puts ("いちごのショートケーキ");
#else
	puts ("ichigo no shōtokēki");
#endif

	if (!pgm_init (&pgm_err)) {
		fprintf (stderr, "Unable to start PGM engine: %s\n", pgm_err->message);
		pgm_error_free (pgm_err);
		return EXIT_FAILURE;
	}

/* parse program arguments */
#ifdef _WIN32
	const char* binary_name = strrchr (argv[0], '\\');
#else
	const char* binary_name = strrchr (argv[0], '/');
#endif
	if (NULL == binary_name)	binary_name = argv[0];
	else				binary_name++;

	int c;
	while ((c = getopt (argc, argv, "s:n:p:f:K:N:lih")) != -1)
	{
		switch (c) {
		case 'n':	network = optarg; break;
		case 's':	port = atoi (optarg); break;
		case 'p':	udp_encap_port = atoi (optarg); break;
		case 'f':	use_fec = TRUE; break;
		case 'K':	rs_k = atoi (optarg); break;
		case 'N':	rs_n = atoi (optarg); break;
		case 'l':	use_multicast_loop = TRUE; break;

		case 'i':
			pgm_if_print_all();
			return EXIT_SUCCESS;

		case 'h':
		case '?': usage (binary_name);
		}
	}

	if (use_fec && ( !rs_n || !rs_k )) {
		fprintf (stderr, "Invalid Reed-Solomon parameters RS(%d,%d).\n", rs_n, rs_k);
		usage (binary_name);
	}

/* setup signal handlers */
#ifdef SIGHUP
	signal (SIGHUP,  SIG_IGN);
#endif
#ifndef _WIN32
	int e = pipe (terminate_pipe);
	assert (0 == e);
	signal (SIGINT,  on_signal);
	signal (SIGTERM, on_signal);
#else
	terminateEvent = WSACreateEvent ();
	SetConsoleCtrlHandler ((PHANDLER_ROUTINE)on_console_ctrl, TRUE);
	setvbuf (stdout, (char *) NULL, _IONBF, 0);
#endif /* !_WIN32 */

	if (!on_startup()) {
		fprintf (stderr, "Startup failed\n");
		return EXIT_FAILURE;
	}

/* dispatch loop */
#ifndef _WIN32
	int fds, read_fd = async_get_socket (async);
	fd_set readfds;
#else
	DWORD cEvents = 2;
	WSAEVENT waitEvents[ 2 ];
	DWORD dwEvents;

	waitEvents[0] = terminateEvent;
	waitEvents[1] = async_get_event (async);
#endif /* !_WIN32 */
	puts ("Entering PGM message loop ... ");
	do {
		char buffer[4096];
		struct pgm_sockaddr_t from;
		socklen_t fromlen = sizeof (from);
		const ssize_t len = async_recvfrom (async,
					            buffer,
					            sizeof(buffer),
					            &from,
						    &fromlen);
		if (len >= 0) {
			on_data (buffer, len, &from);
		} else {
#ifndef _WIN32
			fds = MAX(terminate_pipe[0], read_fd) + 1;
			FD_ZERO(&readfds);
			FD_SET(terminate_pipe[0], &readfds);
			FD_SET(read_fd, &readfds);
			fds = select (fds, &readfds, NULL, NULL, NULL);
#else
			dwEvents = WSAWaitForMultipleEvents (cEvents, waitEvents, FALSE, WSA_INFINITE, FALSE);
			switch (dwEvents) {
			case WSA_WAIT_EVENT_0+1: WSAResetEvent (waitEvents[1]); break;
			default: break;
			}
#endif /* _WIN32 */
		}
	} while (!is_terminated);

	puts ("Message loop terminated, cleaning up.");

/* cleanup */
#ifndef _WIN32
	close (terminate_pipe[0]);
	close (terminate_pipe[1]);
#else
	WSACloseEvent (terminateEvent);
#endif /* !_WIN32 */

	if (async) {
		puts ("Destroying asynchronous queue.");
		async_destroy (async);
		async = NULL;
	}

	if (sock) {
		puts ("Closing PGM socket.");
		pgm_close (sock, TRUE);
		sock = NULL;
	}

	puts ("PGM engine shutdown.");
	pgm_shutdown ();
	puts ("finished.");
	return EXIT_SUCCESS;
}