Commit 0224c2bd authored by Jens Gustedt's avatar Jens Gustedt
Browse files

add iterator and event notifier

parent 89931905
/* This may look like nonsense, but it really is -*- mode: C -*- */
/* */
/* Except for parts copied from previous work and as explicitly stated below, */
/* the author and copyright holder for this work is */
/* (C) copyright 2012 Jens Gustedt, INRIA, France */
/* */
/* This file is free software; it is part of the P99 project. */
/* You can redistribute it and/or modify it under the terms of the QPL as */
/* given in the file LICENSE. It is distributed without any warranty; */
/* without even the implied warranty of merchantability or fitness for a */
/* particular purpose. */
/* */
#ifndef P99_ITERATOR_H
#define P99_ITERATOR_H
#include "p99_futex.h"
/**
** @addtogroup futex
** @{
**/
P99_DECLARE_STRUCT(p99_iterator);
/**
** @brief Iterate over a series events that are signaled by other
** threads.
**
** A @c for-loop like the following
** @code
** p99_iterator it;
** p99_iterator_init(&it);
** .
** .
** for (unsigned i = p99_iterator_next(&it);
** i < n;
** i = p99_iterator_next(&it))
** do_something_with(A[i]);
** @endcode
**
** will step through @n calls to @c do_something_with as other
** threads signal events through ::p99_iterator_signal.
**
** @see p99_iterator_next
** @see p99_iterator_signal
**/
struct p99_iterator {
unsigned p00_act;
p99_futex p00_seen;
};
/**
** @brief Initialize an iterator
** @related p99_iterator
**/
P99_DEFARG_DOCU(p99_iterator_init)
p99_inline
p99_iterator* p99_iterator_init(p99_iterator* p00_i) {
if (p00_i) {
p00_i->p00_act = 0;
p99_futex_init(&p00_i->p00_seen, 0);
}
return p00_i;
}
/**
** @brief destroy a iterator
** @related p99_iterator
**/
p99_inline
void p99_iterator_destroy(p99_iterator* p00_i) {
if (p00_i) {
p99_futex_destroy(&p00_i->p00_seen);
}
}
/**
** @brief Block until an event has been signaled that has not yet
** been accounted for
**
** Non blocking if enough events already have been signaled.
**
** @related p99_iterator
**/
P99_DEFARG_DOCU(p99_iterator_next)
P00_FUTEX_INLINE(p99_iterator_next)
unsigned p99_iterator_next(p99_iterator volatile* p00_i) {
register unsigned const p00_act = p00_i->p00_act;
P99_FUTEX_COMPARE_EXCHANGE(&p00_i->p00_seen, p00_seen,
/* wait for more events than we have
already processed */
(p00_act < p00_seen),
/* never update */
p00_seen,
/* never wakeup others */
0u, 0u);
p00_i->p00_act = p00_act + 1;
return p00_act;
}
/**
** @brief Signal an event.
**
** @related p99_iterator
**/
P99_DEFARG_DOCU(p99_iterator_signal)
p99_inline
unsigned p99_iterator_signal(p99_iterator volatile* p00_i) {
return p99_futex_add(&p00_i->p00_seen, 1u, 0u, UINT_MAX, 0u, P99_FUTEX_MAX_WAITERS);
}
P99_DECLARE_STRUCT(p99_event);
struct p99_event {
p99_iterator p00_it;
unsigned p00_n;
void ** p00_event;
};
/**
** @brief Initialize an event
** @related p99_event
**/
P99_DEFARG_DOCU(p99_event_init)
p99_inline
p99_event* p99_event_init(p99_event* p00_e, unsigned p00_n) {
if (p00_e) {
(*p00_e) = (p99_event) {
.p00_n = p00_n,
.p00_event = P99_MEMZERO(void_ptr, P99_MALLOC(void_ptr[p00_n]), p00_n),
};
p99_iterator_init(&p00_e->p00_it);
}
return p00_e;
}
/**
** @brief destroy an event
** @related p99_event
**/
p99_inline
void p99_event_destroy(p99_event* p00_e) {
if (p00_e) {
free(p00_e->p00_event);
p99_iterator_destroy(&p00_e->p00_it);
}
}
/**
** @brief Block until an event has been signaled that has not yet
** been accounted for
**
** Non blocking if enough events already have been signaled.
**
** @related p99_event
**/
P99_DEFARG_DOCU(p99_event_next)
P00_FUTEX_INLINE(p99_event_next)
void* p99_event_next(p99_event volatile* p00_e) {
P99_FPRINTF(stderr, "next event on %s\n", (void*)p00_e);
unsigned p00_pos = p99_iterator_next(&p00_e->p00_it);
void* p00_ret = 0;
if (p00_pos < p00_e->p00_n)
while (!(p00_ret = p00_e->p00_event[p00_pos]));
P99_FPRINTF(stderr, "next event on %s, returns %s pos %s\n", (void*)p00_e, p00_ret, p00_pos);
return p00_ret;
}
/**
** @brief Signal the event. @a p00_w
**
** @related p99_event
**/
P99_DEFARG_DOCU(p99_event_signal)
p99_inline
void p99_event_signal(p99_event volatile* p00_e, void * p00_w) {
if (p00_e) {
unsigned p00_ret = p99_iterator_signal(&p00_e->p00_it);
p00_e->p00_event[p00_ret] = p00_w;
}
}
/**
** @}
**/
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment