Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Jens Gustedt
P99 - macros and functions for C99
Commits
0224c2bd
Commit
0224c2bd
authored
Dec 03, 2012
by
Jens Gustedt
Browse files
add iterator and event notifier
parent
89931905
Changes
1
Hide whitespace changes
Inline
Side-by-side
p99/p99_iterator.h
0 → 100644
View file @
0224c2bd
/* 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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment