static ChimpRef * chimp_task_new_local (ChimpTaskInternal *task) { ChimpRef *taskobj = chimp_class_new_instance (chimp_task_class, NULL); if (taskobj == NULL) { return NULL; } CHIMP_TASK(taskobj)->priv = task; CHIMP_TASK(taskobj)->local = CHIMP_TRUE; task->refs++; return taskobj; }
static ChimpRef * chimp_symtable_entry_new ( ChimpRef *symtable, ChimpRef *parent, ChimpRef *scope, int flags) { ChimpRef *flags_obj = chimp_int_new (flags); if (flags_obj == NULL) { return NULL; } symtable = symtable ? symtable : chimp_nil; parent = parent ? parent : chimp_nil; scope = scope ? scope : chimp_nil; return chimp_class_new_instance ( chimp_symtable_entry_class, symtable, parent, scope, flags_obj, NULL); }
ChimpRef * chimp_task_new_from_internal (ChimpTaskInternal *priv) { ChimpRef *ref = chimp_class_new_instance (chimp_task_class, NULL); if (ref == NULL) { return NULL; } /* XXX blatant copy/paste from chimp_task_new */ CHIMP_TASK_LOCK(priv); while (!CHIMP_TASK_IS_READY(priv)) { if (pthread_cond_wait (&priv->flags_cond, &priv->lock) != 0) { CHIMP_TASK_UNLOCK(priv); return NULL; } } CHIMP_TASK(ref)->priv = priv; CHIMP_TASK(ref)->local = CHIMP_FALSE; priv->refs++; CHIMP_TASK_UNLOCK(priv); return ref; }
ChimpRef * chimp_task_new (ChimpRef *callable) { ChimpRef *taskobj; pthread_attr_t attrs; ChimpTaskInternal *task = CHIMP_MALLOC(ChimpTaskInternal, sizeof(*task)); if (task == NULL) { return NULL; } memset (task, 0, sizeof (*task)); /* XXX can we guarantee callable won't be collected? think so ... */ task->method = callable; task->flags = 0; /* !!! important to incref *BEFORE* we start the task thread !!! */ /* (otherwise, short-lived tasks can prematurely kill the TaskInternal) */ task->refs++; if (pthread_mutex_init (&task->lock, NULL) != 0) { CHIMP_FREE (task); return NULL; } if (pthread_cond_init (&task->flags_cond, NULL) != 0) { pthread_mutex_destroy (&task->lock); CHIMP_FREE (task); return NULL; } if (pthread_attr_init (&attrs) != 0) { pthread_cond_destroy (&task->flags_cond); pthread_mutex_destroy (&task->lock); return NULL; } if (pthread_attr_setdetachstate (&attrs, PTHREAD_CREATE_DETACHED) != 0) { pthread_attr_destroy (&attrs); pthread_cond_destroy (&task->flags_cond); pthread_mutex_destroy (&task->lock); return NULL; } CHIMP_TASK_LOCK(task); if (pthread_create (&task->thread, &attrs, chimp_task_thread_func, task) != 0) { pthread_attr_destroy (&attrs); pthread_cond_destroy (&task->flags_cond); pthread_mutex_destroy (&task->lock); CHIMP_FREE (task); return NULL; } pthread_attr_destroy (&attrs); /* XXX error handling code is probably all kinds of wrong/unsafe from * this point, but meh. */ while (!CHIMP_TASK_IS_READY(task)) { if (pthread_cond_wait (&task->flags_cond, &task->lock) != 0) { CHIMP_TASK_UNLOCK(task); pthread_cond_destroy (&task->flags_cond); pthread_mutex_destroy (&task->lock); CHIMP_FREE (task); return NULL; } } /* create a heap-local handle for this task */ taskobj = chimp_class_new_instance (chimp_task_class, NULL); if (taskobj == NULL) { CHIMP_TASK_UNLOCK (task); pthread_cond_destroy (&task->flags_cond); pthread_mutex_destroy (&task->lock); CHIMP_FREE (task); return NULL; } CHIMP_TASK(taskobj)->priv = task; CHIMP_TASK(taskobj)->local = CHIMP_FALSE; CHIMP_TASK_UNLOCK(task); return taskobj; }