ARGOBOTS  dce6e727ffc4ca5b3ffc04cb9517c6689be51ec5
futures.c
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #include "abti.h"
7 
61 int ABT_future_create(uint32_t num_compartments, void (*cb_func)(void **arg),
62  ABT_future *newfuture)
63 {
65  ABTI_UB_ASSERT(newfuture);
66 
67  int abt_errno;
68  ABTI_future *p_future;
69  size_t arg_num_compartments = num_compartments;
70 
71  abt_errno = ABTU_malloc(sizeof(ABTI_future), (void **)&p_future);
72  ABTI_CHECK_ERROR(abt_errno);
73  ABTD_spinlock_clear(&p_future->lock);
74  ABTD_atomic_relaxed_store_size(&p_future->counter, 0);
75  p_future->num_compartments = arg_num_compartments;
76  if (arg_num_compartments > 0) {
77  abt_errno = ABTU_malloc(arg_num_compartments * sizeof(void *),
78  (void **)&p_future->array);
79  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
80  ABTU_free(p_future);
81  ABTI_HANDLE_ERROR(abt_errno);
82  }
83  } else {
84  p_future->array = NULL;
85  }
86  p_future->p_callback = cb_func;
87  ABTI_waitlist_init(&p_future->waitlist);
88 
89  *newfuture = ABTI_future_get_handle(p_future);
90  return ABT_SUCCESS;
91 }
92 
120 {
122  ABTI_UB_ASSERT(future);
123 
124  ABTI_future *p_future = ABTI_future_get_ptr(*future);
125  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
126 
127  /* The lock needs to be acquired to safely free the future structure.
128  * However, we do not have to unlock it because the entire structure is
129  * freed here. */
130  ABTD_spinlock_acquire(&p_future->lock);
132 
133  ABTU_free(p_future->array);
134  ABTU_free(p_future);
135 
136  *future = ABT_FUTURE_NULL;
137  return ABT_SUCCESS;
138 }
139 
173 {
175 
176  ABTI_local *p_local = ABTI_local_get_local();
177  ABTI_future *p_future = ABTI_future_get_ptr(future);
178  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
179 
180 #ifndef ABT_CONFIG_ENABLE_VER_20_API
181  /* Calling this routine on a tasklet is not allowed. */
182  if (ABTI_IS_ERROR_CHECK_ENABLED && p_local) {
183  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
184  ABTI_CHECK_TRUE(p_local_xstream->p_thread->type &
187  }
188 #endif
189 
190  ABTD_spinlock_acquire(&p_future->lock);
191  if (ABTD_atomic_relaxed_load_size(&p_future->counter) <
192  p_future->num_compartments) {
193  ABTI_waitlist_wait_and_unlock(&p_local, &p_future->waitlist,
194  &p_future->lock,
196  (void *)p_future);
197  } else {
198  ABTD_spinlock_release(&p_future->lock);
199  }
200  return ABT_SUCCESS;
201 }
202 
229 int ABT_future_test(ABT_future future, ABT_bool *is_ready)
230 {
232  ABTI_UB_ASSERT(is_ready);
233 
234  ABTI_future *p_future = ABTI_future_get_ptr(future);
235  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
236 
237  size_t counter = ABTD_atomic_acquire_load_size(&p_future->counter);
238  *is_ready = (counter == p_future->num_compartments) ? ABT_TRUE : ABT_FALSE;
239  return ABT_SUCCESS;
240 }
241 
270 int ABT_future_set(ABT_future future, void *value)
271 {
273 
274  ABTI_local *p_local = ABTI_local_get_local();
275  ABTI_future *p_future = ABTI_future_get_ptr(future);
276  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
277 
278  ABTD_spinlock_acquire(&p_future->lock);
279 
280  size_t counter = ABTD_atomic_relaxed_load_size(&p_future->counter);
281  size_t num_compartments = p_future->num_compartments;
282 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
283  /* If num_compartments is 0, this routine always returns ABT_ERR_FUTURE */
284  if (counter >= num_compartments) {
285  ABTD_spinlock_release(&p_future->lock);
287  }
288 #endif
289  p_future->array[counter] = value;
290  counter++;
291  /* Call a callback function before setting the counter. */
292  if (counter == num_compartments && p_future->p_callback != NULL) {
293  (*p_future->p_callback)(p_future->array);
294  }
295 
296  ABTD_atomic_release_store_size(&p_future->counter, counter);
297 
298  if (counter == num_compartments) {
299  ABTI_waitlist_broadcast(p_local, &p_future->waitlist);
300  }
301 
302  ABTD_spinlock_release(&p_future->lock);
303  return ABT_SUCCESS;
304 }
305 
338 {
340 
341  ABTI_future *p_future = ABTI_future_get_ptr(future);
342  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
343 
344  ABTD_spinlock_acquire(&p_future->lock);
347  ABTD_spinlock_release(&p_future->lock);
348  return ABT_SUCCESS;
349 }
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
ABTI_future::array
void ** array
Definition: abti.h:508
ABTD_atomic_release_store_size
static void ABTD_atomic_release_store_size(ABTD_atomic_size *ptr, size_t val)
Definition: abtd_atomic.h:1076
ABTI_waitlist_broadcast
static void ABTI_waitlist_broadcast(ABTI_local *p_local, ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:246
ABTI_future
Definition: abti.h:504
ABT_future_free
int ABT_future_free(ABT_future *future)
Free a future.
Definition: futures.c:119
ABT_future_wait
int ABT_future_wait(ABT_future future)
Wait on a future.
Definition: futures.c:172
ABTI_CHECK_ERROR
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:136
ABTI_xstream::type
ABTI_xstream_type type
Definition: abti.h:300
ABTI_THREAD_TYPE_YIELDABLE
#define ABTI_THREAD_TYPE_YIELDABLE
Definition: abti.h:87
ABTI_future_get_handle
static ABT_future ABTI_future_get_handle(ABTI_future *p_future)
Definition: abti_future.h:26
ABT_ERR_FUTURE
#define ABT_ERR_FUTURE
Error code: error related to a future.
Definition: abt.h:355
ABTI_future::counter
ABTD_atomic_size counter
Definition: abti.h:506
ABT_SYNC_EVENT_TYPE_FUTURE
@ ABT_SYNC_EVENT_TYPE_FUTURE
Definition: abt.h:716
ABTI_IS_ERROR_CHECK_ENABLED
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
ABT_future_create
int ABT_future_create(uint32_t num_compartments, void(*cb_func)(void **arg), ABT_future *newfuture)
Create a new future.
Definition: futures.c:61
ABTI_xstream
Definition: abti.h:294
ABTI_future::num_compartments
size_t num_compartments
Definition: abti.h:507
ABTI_waitlist_is_empty
static ABT_bool ABTI_waitlist_is_empty(ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:282
abti.h
ABTD_spinlock_acquire
static void ABTD_spinlock_acquire(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:28
ABTI_HANDLE_ERROR
#define ABTI_HANDLE_ERROR(n)
Definition: abti_error.h:130
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABT_future
struct ABT_future_opaque * ABT_future
Future handle type.
Definition: abt.h:1022
ABTD_atomic_relaxed_load_size
static size_t ABTD_atomic_relaxed_load_size(const ABTD_atomic_size *ptr)
Definition: abtd_atomic.h:776
ABTD_atomic_acquire_load_size
static size_t ABTD_atomic_acquire_load_size(const ABTD_atomic_size *ptr)
Definition: abtd_atomic.h:894
ABTD_atomic_relaxed_store_size
static void ABTD_atomic_relaxed_store_size(ABTD_atomic_size *ptr, size_t val)
Definition: abtd_atomic.h:1005
ABTI_initialized
ABT_bool ABTI_initialized(void)
Definition: global.c:187
ABTI_local_get_local
static ABTI_local * ABTI_local_get_local(void)
Definition: abti_local.h:41
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABT_TRUE
#define ABT_TRUE
True constant for ABT_bool.
Definition: abt.h:784
ABTI_CHECK_NULL_FUTURE_PTR
#define ABTI_CHECK_NULL_FUTURE_PTR(p)
Definition: abti_error.h:310
ABTD_spinlock_clear
static void ABTD_spinlock_clear(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:23
ABTI_future::lock
ABTD_spinlock lock
Definition: abti.h:505
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:786
ABT_future_set
int ABT_future_set(ABT_future future, void *value)
Signal a future.
Definition: futures.c:270
ABTI_UB_ASSERT
#define ABTI_UB_ASSERT(cond)
Definition: abti_error.h:19
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
ABTD_spinlock_release
static void ABTD_spinlock_release(ABTD_spinlock *p_lock)
Definition: abtd_spinlock.h:42
ABTI_future::waitlist
ABTI_waitlist waitlist
Definition: abti.h:510
ABT_future_reset
int ABT_future_reset(ABT_future future)
Reset readiness of a future.
Definition: futures.c:337
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:132
ABTI_CHECK_TRUE
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:146
ABTI_waitlist_init
static void ABTI_waitlist_init(ABTI_waitlist *p_waitlist)
Definition: abti_waitlist.h:11
ABTI_local_get_xstream
static ABTI_xstream * ABTI_local_get_xstream(ABTI_local *p_local)
Definition: abti_local.h:86
ABTI_waitlist_wait_and_unlock
static void ABTI_waitlist_wait_and_unlock(ABTI_local **pp_local, ABTI_waitlist *p_waitlist, ABTD_spinlock *p_lock, ABT_sync_event_type sync_event_type, void *p_sync)
Definition: abti_waitlist.h:21
ABTI_future::p_callback
void(* p_callback)(void **arg)
Definition: abti.h:509
ABTI_future_get_ptr
static ABTI_future * ABTI_future_get_ptr(ABT_future future)
Definition: abti_future.h:11
ABT_FUTURE_NULL
#define ABT_FUTURE_NULL
Definition: abt.h:1114
ABT_future_test
int ABT_future_test(ABT_future future, ABT_bool *is_ready)
Check if a future is ready.
Definition: futures.c:229