@@ -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.
0 commit comments