Skip to content

Commit 6e21abc

Browse files
authored
Merge pull request #408 from pmodels/mdorier/add-ABT_eventual_timedwait
eventual: added ABT_eventual_timedwait
2 parents 52421fc + dda742d commit 6e21abc

File tree

4 files changed

+386
-2
lines changed

4 files changed

+386
-2
lines changed

src/eventual.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,110 @@ int ABT_eventual_wait(ABT_eventual eventual, void **value)
205205
return ABT_SUCCESS;
206206
}
207207

208+
static inline double convert_timespec_to_sec(const struct timespec *p_ts)
209+
{
210+
double secs;
211+
secs = ((double)p_ts->tv_sec) + 1.0e-9 * ((double)p_ts->tv_nsec);
212+
return secs;
213+
}
214+
215+
/**
216+
* @ingroup EVENTUAL
217+
* @brief Wait on an eventual with a timeout.
218+
*
219+
* \c ABT_eventual_timedwait() blocks the caller until the eventual \c eventual
220+
* is signaled by \c ABT_eventual_set() or until the absolute timeout specified
221+
* by \c abstime is reached. If the eventual is already ready when this function
222+
* is called, the caller will not be blocked and the value will be returned
223+
* immediately.
224+
*
225+
* If \c value is not \c NULL, \c value is set to the memory buffer of
226+
* \c eventual. If \c value is not \c NULL but the size of the memory buffer of
227+
* \c eventual (i.e., \c nbytes passed to \c ABT_eventual_create()) is zero,
228+
* \c value is set to \c NULL.
229+
*
230+
* The memory buffer pointed to by \c value is deallocated when \c eventual is
231+
* freed by \c ABT_eventual_free(). The memory buffer is properly aligned for
232+
* storage of any type of object that has the given size. If the data written
233+
* by \c ABT_eventual_set() is smaller than the size of the memory buffer of
234+
* \c eventual, the contents of the memory buffer that was not written by
235+
* \c ABT_eventual_set() are undefined. The contents of the memory buffer get
236+
* undefined if either \c ABT_eventual_set() or \c ABT_eventual_reset() is
237+
* called for \c eventual. The memory buffer is read-only, so rewriting the
238+
* contents of the obtained memory buffer causes undefined behavior.
239+
*
240+
* \DOC_DESC_ATOMICITY_EVENTUAL_READINESS
241+
*
242+
* @changev20
243+
* \DOC_DESC_V1X_NOTASK{\c ABT_ERR_EVENTUAL}
244+
* @endchangev20
245+
*
246+
* @contexts
247+
* \DOC_V1X \DOC_CONTEXT_INIT_NOTASK \DOC_CONTEXT_CTXSWITCH_CONDITIONAL{
248+
* \c eventual is not ready}\n
249+
* \DOC_V20 \DOC_CONTEXT_INIT \DOC_CONTEXT_CTXSWITCH_CONDITIONAL{\c eventual is
250+
* not ready}
251+
*
252+
* @errors
253+
* \DOC_ERROR_SUCCESS
254+
* \DOC_ERROR_INV_EVENTUAL_HANDLE{\c eventual}
255+
* \DOC_ERROR_COND_TIMEDOUT
256+
* \DOC_V1X \DOC_ERROR_TASK{\c ABT_ERR_EVENTUAL}
257+
*
258+
* @undefined
259+
* \DOC_UNDEFINED_UNINIT
260+
* \DOC_UNDEFINED_NULL_PTR{\c abstime}
261+
* \DOC_UNDEFINED_EVENTUAL_BUFFER{\c eventual, \c value}
262+
*
263+
* @param[in] eventual eventual handle
264+
* @param[out] value memory buffer of the eventual
265+
* @param[in] abstime absolute timeout
266+
* @return Error code
267+
*/
268+
int ABT_eventual_timedwait(ABT_eventual eventual, void **value,
269+
const struct timespec *abstime)
270+
{
271+
ABTI_UB_ASSERT(ABTI_initialized());
272+
ABTI_UB_ASSERT(abstime);
273+
274+
ABTI_local *p_local = ABTI_local_get_local();
275+
ABTI_eventual *p_eventual = ABTI_eventual_get_ptr(eventual);
276+
ABTI_CHECK_NULL_EVENTUAL_PTR(p_eventual);
277+
278+
#ifndef ABT_CONFIG_ENABLE_VER_20_API
279+
/* This routine cannot be called by a tasklet. */
280+
if (ABTI_IS_ERROR_CHECK_ENABLED && p_local) {
281+
ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
282+
ABTI_CHECK_TRUE(p_local_xstream->p_thread->type &
283+
ABTI_THREAD_TYPE_YIELDABLE,
284+
ABT_ERR_EVENTUAL);
285+
}
286+
#endif
287+
288+
double tar_time = convert_timespec_to_sec(abstime);
289+
290+
ABTD_spinlock_acquire(&p_eventual->lock);
291+
if (p_eventual->ready == ABT_FALSE) {
292+
ABT_bool is_timedout =
293+
ABTI_waitlist_wait_timedout_and_unlock(&p_local,
294+
&p_eventual->waitlist,
295+
&p_eventual->lock, tar_time,
296+
ABT_SYNC_EVENT_TYPE_EVENTUAL,
297+
(void *)p_eventual);
298+
if (is_timedout) {
299+
return ABT_ERR_COND_TIMEDOUT;
300+
}
301+
} else {
302+
ABTD_spinlock_release(&p_eventual->lock);
303+
}
304+
/* This value is updated outside the critical section, but it is okay since
305+
* the "pointer" to the memory buffer is constant and there is no way to
306+
* avoid updating this memory buffer by ABT_eventual_set() etc. */
307+
if (value)
308+
*value = p_eventual->value;
309+
return ABT_SUCCESS;
310+
}
311+
208312
/**
209313
* @ingroup EVENTUAL
210314
* @brief Check if an eventual is ready.

src/include/abt.h.in

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,10 @@ extern "C" {
333333
#define ABT_ERR_COND 41
334334
/**
335335
* @ingroup ERROR_CODE
336-
* @brief Error code: a return value when a condition variable is timed out.
336+
* @brief Error code: a return value when a timed wait operation times out.
337337
*
338-
* This error code is used by \c ABT_cond_timedwait().
338+
* This error code is used by \c ABT_cond_timedwait() and
339+
* \c ABT_eventual_timedwait().
339340
*/
340341
#define ABT_ERR_COND_TIMEDOUT 42
341342
/**
@@ -2635,6 +2636,8 @@ int ABT_rwlock_unlock(ABT_rwlock rwlock) ABT_API_PUBLIC;
26352636
int ABT_eventual_create(int nbytes, ABT_eventual *neweventual) ABT_API_PUBLIC;
26362637
int ABT_eventual_free(ABT_eventual *eventual) ABT_API_PUBLIC;
26372638
int ABT_eventual_wait(ABT_eventual eventual, void **value) ABT_API_PUBLIC;
2639+
int ABT_eventual_timedwait(ABT_eventual eventual, void **value,
2640+
const struct timespec *abstime) ABT_API_PUBLIC;
26382641
int ABT_eventual_test(ABT_eventual eventual, void **value, ABT_bool *is_ready) ABT_API_PUBLIC;
26392642
int ABT_eventual_set(ABT_eventual eventual, void *value, int nbytes) ABT_API_PUBLIC;
26402643
int ABT_eventual_reset(ABT_eventual eventual) ABT_API_PUBLIC;

test/basic/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ TESTS = \
7070
eventual_create \
7171
eventual_static \
7272
eventual_test \
73+
eventual_timedwait \
7374
barrier \
7475
self_exit_to \
7576
self_rank_id \
@@ -177,6 +178,7 @@ future_create_SOURCES = future_create.c
177178
eventual_create_SOURCES = eventual_create.c
178179
eventual_static_SOURCES = eventual_static.c
179180
eventual_test_SOURCES = eventual_test.c
181+
eventual_timedwait_SOURCES = eventual_timedwait.c
180182
barrier_SOURCES = barrier.c
181183
self_exit_to_SOURCES = self_exit_to.c
182184
self_rank_id_SOURCES = self_rank_id.c

0 commit comments

Comments
 (0)