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 {
64  ABTI_UB_ASSERT(ABTI_initialized());
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 {
121  ABTI_UB_ASSERT(ABTI_initialized());
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);
131  ABTI_UB_ASSERT(ABTI_waitlist_is_empty(&p_future->waitlist));
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 {
174  ABTI_UB_ASSERT(ABTI_initialized());
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 &
185  ABTI_THREAD_TYPE_YIELDABLE,
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 {
231  ABTI_UB_ASSERT(ABTI_initialized());
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 {
272  ABTI_UB_ASSERT(ABTI_initialized());
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);
286  ABTI_HANDLE_ERROR(ABT_ERR_FUTURE);
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 {
339  ABTI_UB_ASSERT(ABTI_initialized());
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);
345  ABTI_UB_ASSERT(ABTI_waitlist_is_empty(&p_future->waitlist));
346  ABTD_atomic_release_store_size(&p_future->counter, 0);
347  ABTD_spinlock_release(&p_future->lock);
348  return ABT_SUCCESS;
349 }
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1043
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
ABT_ERR_FUTURE
#define ABT_ERR_FUTURE
Error code: error related to a future.
Definition: abt.h:355
ABT_SYNC_EVENT_TYPE_FUTURE
@ ABT_SYNC_EVENT_TYPE_FUTURE
Definition: abt.h:716
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.h
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
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
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
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
ABT_future_reset
int ABT_future_reset(ABT_future future)
Reset readiness of a future.
Definition: futures.c:337
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