ARGOBOTS  1.1
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  int abt_errno;
65  ABTI_future *p_future;
66  size_t arg_num_compartments = num_compartments;
67 
68  abt_errno = ABTU_malloc(sizeof(ABTI_future), (void **)&p_future);
69  ABTI_CHECK_ERROR(abt_errno);
70  ABTD_spinlock_clear(&p_future->lock);
71  ABTD_atomic_relaxed_store_size(&p_future->counter, 0);
72  p_future->num_compartments = arg_num_compartments;
73  if (arg_num_compartments > 0) {
74  abt_errno = ABTU_malloc(arg_num_compartments * sizeof(void *),
75  (void **)&p_future->array);
76  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
77  ABTU_free(p_future);
78  ABTI_HANDLE_ERROR(abt_errno);
79  }
80  } else {
81  p_future->array = NULL;
82  }
83  p_future->p_callback = cb_func;
84  ABTI_waitlist_init(&p_future->waitlist);
85 
86  *newfuture = ABTI_future_get_handle(p_future);
87  return ABT_SUCCESS;
88 }
89 
117 {
118  ABTI_future *p_future = ABTI_future_get_ptr(*future);
119  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
120 
121  /* The lock needs to be acquired to safely free the future structure.
122  * However, we do not have to unlock it because the entire structure is
123  * freed here. */
124  ABTD_spinlock_acquire(&p_future->lock);
125 
126  ABTU_free(p_future->array);
127  ABTU_free(p_future);
128 
129  *future = ABT_FUTURE_NULL;
130  return ABT_SUCCESS;
131 }
132 
166 {
167  ABTI_local *p_local = ABTI_local_get_local();
168  ABTI_future *p_future = ABTI_future_get_ptr(future);
169  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
170 
171 #ifndef ABT_CONFIG_ENABLE_VER_20_API
172  /* Calling this routine on a tasklet is not allowed. */
173  if (ABTI_IS_ERROR_CHECK_ENABLED && p_local) {
174  ABTI_xstream *p_local_xstream = ABTI_local_get_xstream(p_local);
175  ABTI_CHECK_TRUE(p_local_xstream->p_thread->type &
178  }
179 #endif
180 
181  ABTD_spinlock_acquire(&p_future->lock);
182  if (ABTD_atomic_relaxed_load_size(&p_future->counter) <
183  p_future->num_compartments) {
184  ABTI_waitlist_wait_and_unlock(&p_local, &p_future->waitlist,
185  &p_future->lock,
187  (void *)p_future);
188  } else {
189  ABTD_spinlock_release(&p_future->lock);
190  }
191  return ABT_SUCCESS;
192 }
193 
220 int ABT_future_test(ABT_future future, ABT_bool *is_ready)
221 {
222  ABTI_future *p_future = ABTI_future_get_ptr(future);
223  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
224 
225  size_t counter = ABTD_atomic_acquire_load_size(&p_future->counter);
226  *is_ready = (counter == p_future->num_compartments) ? ABT_TRUE : ABT_FALSE;
227  return ABT_SUCCESS;
228 }
229 
258 int ABT_future_set(ABT_future future, void *value)
259 {
260  ABTI_local *p_local = ABTI_local_get_local();
261  ABTI_future *p_future = ABTI_future_get_ptr(future);
262  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
263 
264  ABTD_spinlock_acquire(&p_future->lock);
265 
266  size_t counter = ABTD_atomic_relaxed_load_size(&p_future->counter);
267  size_t num_compartments = p_future->num_compartments;
268 #ifndef ABT_CONFIG_DISABLE_ERROR_CHECK
269  /* If num_compartments is 0, this routine always returns ABT_ERR_FUTURE */
270  if (counter >= num_compartments) {
271  ABTD_spinlock_release(&p_future->lock);
273  }
274 #endif
275  p_future->array[counter] = value;
276  counter++;
277  /* Call a callback function before setting the counter. */
278  if (counter == num_compartments && p_future->p_callback != NULL) {
279  (*p_future->p_callback)(p_future->array);
280  }
281 
282  ABTD_atomic_release_store_size(&p_future->counter, counter);
283 
284  if (counter == num_compartments) {
285  ABTI_waitlist_broadcast(p_local, &p_future->waitlist);
286  }
287 
288  ABTD_spinlock_release(&p_future->lock);
289  return ABT_SUCCESS;
290 }
291 
324 {
325  ABTI_future *p_future = ABTI_future_get_ptr(future);
326  ABTI_CHECK_NULL_FUTURE_PTR(p_future);
327 
328  ABTD_spinlock_acquire(&p_future->lock);
330  ABTD_spinlock_release(&p_future->lock);
331  return ABT_SUCCESS;
332 }
ABT_bool
int ABT_bool
Boolean type.
Definition: abt.h:1001
ABTI_future::array
void ** array
Definition: abti.h:460
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:247
ABTI_future
Definition: abti.h:456
ABT_future_free
int ABT_future_free(ABT_future *future)
Free a future.
Definition: futures.c:116
ABT_future_wait
int ABT_future_wait(ABT_future future)
Wait on a future.
Definition: futures.c:165
ABTI_CHECK_ERROR
#define ABTI_CHECK_ERROR(abt_errno)
Definition: abti_error.h:120
ABTI_xstream::type
ABTI_xstream_type type
Definition: abti.h:270
ABTI_THREAD_TYPE_YIELDABLE
#define ABTI_THREAD_TYPE_YIELDABLE
Definition: abti.h:86
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:345
ABTI_future::counter
ABTD_atomic_size counter
Definition: abti.h:458
ABT_SYNC_EVENT_TYPE_FUTURE
@ ABT_SYNC_EVENT_TYPE_FUTURE
Definition: abt.h:680
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:264
ABTI_future::num_compartments
size_t num_compartments
Definition: abti.h:459
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:114
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:262
ABT_future
struct ABT_future_opaque * ABT_future
Future handle type.
Definition: abt.h:980
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_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:748
ABTI_CHECK_NULL_FUTURE_PTR
#define ABTI_CHECK_NULL_FUTURE_PTR(p)
Definition: abti_error.h:276
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:457
ABT_FALSE
#define ABT_FALSE
False constant for ABT_bool.
Definition: abt.h:750
ABT_future_set
int ABT_future_set(ABT_future future, void *value)
Signal a future.
Definition: futures.c:258
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:217
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:462
ABT_future_reset
int ABT_future_reset(ABT_future future)
Reset readiness of a future.
Definition: futures.c:323
ABTI_local
struct ABTI_local ABTI_local
Definition: abti.h:110
ABTI_CHECK_TRUE
#define ABTI_CHECK_TRUE(cond, abt_errno)
Definition: abti_error.h:130
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:461
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:1071
ABT_future_test
int ABT_future_test(ABT_future future, ABT_bool *is_ready)
Check if a future is ready.
Definition: futures.c:220