예제 #1
0
static gboolean
test_force_set(void)
{
    GThread *th;
    amsemaphore_t *sem = amsemaphore_new_with_value(10);

    th = g_thread_create(test_force_set_thread, (gpointer)sem, TRUE, NULL);

    /* sleep to give amsemaphore_decrement() a chance to block (or not). */
    g_usleep(G_USEC_PER_SEC / 4);

    /* set it to 30, so decrement can proceed, but leave the value at 10 */
    amsemaphore_force_set(sem, 30);

    /* sleep to give amsemaphore_wait_empty() a chance to block (or not). */
    g_usleep(G_USEC_PER_SEC / 4);

    /* and empty out the semaphore */
    amsemaphore_force_set(sem, 0);

    g_thread_join(th);

    amsemaphore_free(sem);

    /* it we didn't hang yet, it's all good */
    return TRUE;
}
예제 #2
0
static gboolean
test_decr_wait(void)
{
    GThread *th;
    struct test_decr_wait_data data = { NULL, FALSE };
    int rv;

    data.sem = amsemaphore_new_with_value(10),

    th = g_thread_create(test_decr_wait_thread, (gpointer)&data, TRUE, NULL);

    /* sleep to give amsemaphore_decrement() a chance to block (or not). */
    g_usleep(G_USEC_PER_SEC / 4);

    /* and then increment the semaphore enough that the decrement can succeed */
    data.increment_called = TRUE;
    amsemaphore_increment(data.sem, 10);

    /* join the thread and see how it fared. */
    rv = GPOINTER_TO_INT(g_thread_join(th));

    amsemaphore_free(data.sem);

    return (rv == 1);
}
예제 #3
0
static gboolean
test_wait_empty(void)
{
    GThread *th;
    amsemaphore_t *sem = amsemaphore_new_with_value(10);
    int rv;

    th = g_thread_create(test_wait_empty_thread, (gpointer)sem, TRUE, NULL);

    /* sleep to give amsemaphore_decrement() a chance to block (or not). */
    g_usleep(G_USEC_PER_SEC / 4);

    /* add another 10, so decrement can hit zero next time it's called */
    amsemaphore_increment(sem, 10);

    /* and wait on the semaphore emptying */
    amsemaphore_wait_empty(sem);

    /* join the thread and see how it fared. */
    rv = GPOINTER_TO_INT(g_thread_join(th));

    amsemaphore_free(sem);

    return (rv == 1);
}
예제 #4
0
static gboolean
setup_impl(
    XferElement *elt)
{
    XferElementGlue *self = (XferElementGlue *)elt;
    gboolean need_ring = FALSE;
    gboolean need_listen_input = FALSE;
    gboolean need_listen_output = FALSE;

    g_assert(elt->input_mech != XFER_MECH_NONE);
    g_assert(elt->output_mech != XFER_MECH_NONE);
    g_assert(elt->input_mech != elt->output_mech);

    self->read_fdp = NULL;
    self->write_fdp = NULL;
    self->on_push = PUSH_INVALID;
    self->on_pull = PULL_INVALID;
    self->need_thread = FALSE;

    switch (mech_pair(elt->input_mech, elt->output_mech)) {
    case mech_pair(XFER_MECH_READFD, XFER_MECH_WRITEFD):
	/* thread will read from one fd and write to the other */
	self->read_fdp = &neighboring_element_fd;
	self->write_fdp = &neighboring_element_fd;
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_READFD, XFER_MECH_PUSH_BUFFER):
	/* thread will read from one fd and call push_buffer downstream */
	self->read_fdp = &neighboring_element_fd;
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_READFD, XFER_MECH_PULL_BUFFER):
	self->read_fdp = &neighboring_element_fd;
	self->on_pull = PULL_FROM_FD;
	break;

    case mech_pair(XFER_MECH_READFD, XFER_MECH_DIRECTTCP_LISTEN):
	/* thread will connect for output, then read from fd and write to the
	 * socket. */
	self->read_fdp = &neighboring_element_fd;
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_READFD, XFER_MECH_DIRECTTCP_CONNECT):
	/* thread will accept output conn, then read from upstream and write to socket */
	self->read_fdp = &neighboring_element_fd;
	self->need_thread = TRUE;
	need_listen_output = TRUE;
	break;

    case mech_pair(XFER_MECH_WRITEFD, XFER_MECH_READFD):
	make_pipe(self);
	g_assert(xfer_element_swap_input_fd(elt, self->pipe[1]) == -1);
	self->pipe[1] = -1; /* upstream will close this for us */
	g_assert(xfer_element_swap_output_fd(elt, self->pipe[0]) == -1);
	self->pipe[0] = -1; /* downstream will close this for us */
	break;

    case mech_pair(XFER_MECH_WRITEFD, XFER_MECH_PUSH_BUFFER):
	/* thread will read from pipe and call downstream's push_buffer */
	make_pipe(self);
	g_assert(xfer_element_swap_input_fd(elt, self->pipe[1]) == -1);
	self->pipe[1] = -1; /* upstream will close this for us */
	self->read_fdp = &self->pipe[0];
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_WRITEFD, XFER_MECH_PULL_BUFFER):
	make_pipe(self);
	g_assert(xfer_element_swap_input_fd(elt, self->pipe[1]) == -1);
	self->pipe[1] = -1; /* upstream will close this for us */
	self->on_pull = PULL_FROM_FD;
	self->read_fdp = &self->pipe[0];
	break;

    case mech_pair(XFER_MECH_WRITEFD, XFER_MECH_DIRECTTCP_LISTEN):
	/* thread will connect for output, then read from pipe and write to socket */
	make_pipe(self);
	g_assert(xfer_element_swap_input_fd(elt, self->pipe[1]) == -1);
	self->pipe[1] = -1; /* upstream will close this for us */
	self->read_fdp = &self->pipe[0];
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_WRITEFD, XFER_MECH_DIRECTTCP_CONNECT):
	/* thread will accept output conn, then read from pipe and write to socket */
	make_pipe(self);
	g_assert(xfer_element_swap_input_fd(elt, self->pipe[1]) == -1);
	self->pipe[1] = -1; /* upstream will close this for us */
	self->read_fdp = &self->pipe[0];
	self->need_thread = TRUE;
	need_listen_output = TRUE;
	break;

    case mech_pair(XFER_MECH_PUSH_BUFFER, XFER_MECH_READFD):
	make_pipe(self);
	g_assert(xfer_element_swap_output_fd(elt, self->pipe[0]) == -1);
	self->pipe[0] = -1; /* downstream will close this for us */
	self->on_push = PUSH_TO_FD;
	self->write_fdp = &self->pipe[1];
	break;

    case mech_pair(XFER_MECH_PUSH_BUFFER, XFER_MECH_WRITEFD):
	self->on_push = PUSH_TO_FD;
	self->write_fdp = &neighboring_element_fd;
	break;

    case mech_pair(XFER_MECH_PUSH_BUFFER, XFER_MECH_PULL_BUFFER):
	self->on_push = PUSH_TO_RING_BUFFER;
	self->on_pull = PULL_FROM_RING_BUFFER;
	need_ring = TRUE;
	break;

    case mech_pair(XFER_MECH_PUSH_BUFFER, XFER_MECH_DIRECTTCP_LISTEN):
	/* push will connect for output first */
	self->on_push = PUSH_TO_FD | PUSH_CONNECT_FIRST;
	break;

    case mech_pair(XFER_MECH_PUSH_BUFFER, XFER_MECH_DIRECTTCP_CONNECT):
	/* push will accept for output first */
	self->on_push = PUSH_TO_FD | PUSH_ACCEPT_FIRST;
	need_listen_output = TRUE;
	break;

    case mech_pair(XFER_MECH_PULL_BUFFER, XFER_MECH_READFD):
	/* thread will pull from upstream and write to pipe */
	make_pipe(self);
	g_assert(xfer_element_swap_output_fd(elt, self->pipe[0]) == -1);
	self->pipe[0] = -1; /* downstream will close this for us */
	self->write_fdp = &self->pipe[1];
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_PULL_BUFFER, XFER_MECH_WRITEFD):
	/* thread will pull from upstream and write to downstream */
	self->write_fdp = &neighboring_element_fd;
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_PULL_BUFFER, XFER_MECH_PUSH_BUFFER):
	/* thread will pull from upstream and push to downstream */
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_PULL_BUFFER, XFER_MECH_DIRECTTCP_LISTEN):
	/* thread will connect for output, then pull from upstream and write to socket */
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_PULL_BUFFER, XFER_MECH_DIRECTTCP_CONNECT):
	/* thread will accept for output, then pull from upstream and write to socket */
	self->need_thread = TRUE;
	need_listen_output = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_LISTEN, XFER_MECH_READFD):
	/* thread will accept for input, then read from socket and write to pipe */
	make_pipe(self);
	g_assert(xfer_element_swap_output_fd(elt, self->pipe[0]) == -1);
	self->pipe[0] = -1; /* downstream will close this for us */
	self->write_fdp = &self->pipe[1];
	self->need_thread = TRUE;
	need_listen_input = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_LISTEN, XFER_MECH_WRITEFD):
	/* thread will accept for input, then read from socket and write to downstream */
	self->write_fdp = &neighboring_element_fd;
	self->need_thread = TRUE;
	need_listen_input = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_LISTEN, XFER_MECH_PUSH_BUFFER):
	/* thread will accept for input, then read from socket and push downstream */
	self->need_thread = TRUE;
	need_listen_input = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_LISTEN, XFER_MECH_PULL_BUFFER):
	/* first pull will accept for input, then read from socket */
	self->on_pull = PULL_FROM_FD | PULL_ACCEPT_FIRST;
	need_listen_input = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_LISTEN, XFER_MECH_DIRECTTCP_CONNECT):
	/* thread will accept on both sides, then copy from socket to socket */
	self->need_thread = TRUE;
	need_listen_input = TRUE;
	need_listen_output = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_CONNECT, XFER_MECH_READFD):
	/* thread will connect for input, then read from socket and write to pipe */
	make_pipe(self);
	g_assert(xfer_element_swap_output_fd(elt, self->pipe[0]) == -1);
	self->pipe[0] = -1; /* downstream will close this for us */
	self->write_fdp = &self->pipe[1];
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_CONNECT, XFER_MECH_WRITEFD):
	/* thread will connect for input, then read from socket and write to downstream */
	self->write_fdp = &neighboring_element_fd;
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_CONNECT, XFER_MECH_PUSH_BUFFER):
	/* thread will connect for input, then read from socket and push downstream */
	self->need_thread = TRUE;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_CONNECT, XFER_MECH_PULL_BUFFER):
	/* first pull will connect for input, then read from socket */
	self->on_pull = PULL_FROM_FD | PULL_CONNECT_FIRST;
	break;

    case mech_pair(XFER_MECH_DIRECTTCP_CONNECT, XFER_MECH_DIRECTTCP_LISTEN):
	/* thread will connect on both sides, then copy from socket to socket */
	self->on_pull = PULL_FROM_FD | PULL_ACCEPT_FIRST;
	self->need_thread = TRUE;
	break;

    default:
	g_assert_not_reached();
	break;
    }

    /* set up ring if desired */
    if (need_ring) {
	self->ring = g_try_malloc(sizeof(*self->ring) * GLUE_RING_BUFFER_SIZE);
	if (self->ring == NULL) {
	    xfer_cancel_with_error(elt, "Can't allocate memory for ring");
	    return FALSE;
	}
	self->ring_used_sem = amsemaphore_new_with_value(0);
	self->ring_free_sem = amsemaphore_new_with_value(GLUE_RING_BUFFER_SIZE);
    }

    if (need_listen_input) {
	if (!do_directtcp_listen(elt,
		    &self->input_listen_socket, &elt->input_listen_addrs))
	    return FALSE;
    }
    if (need_listen_output) {
	if (!do_directtcp_listen(elt,
		    &self->output_listen_socket, &elt->output_listen_addrs))
	    return FALSE;
    }

    return TRUE;
}