/* Build the Command args list. The list represent the array sent to execv and the List contains the following entries: args[0] is the path to the program, the rest are arguments to the program */ static void buildArgs(T C, const char *path, const char *x, va_list ap) { freeStrings(C->args); List_append(C->args, Str_dup(path)); va_list ap_copy; va_copy(ap_copy, ap); for (; x; x = va_arg(ap_copy, char *)) List_append(C->args, Str_dup(x)); va_end(ap_copy); }
/** *** \brief Stores a value in the dictionary with the specified key, maintaining the *** keys in alphabetical order. *** *** If a value with that key already exists in the *** dictionary, it will be replaced with the new value *** \note This is a potential memory leak! **/ bool Dict_putSorted(Dict *d, const char *key, void *value) { bool retVal = false; bool added = false; size_t idx = 0; Pair *p = NULL; Pair *pp = NULL; size_t ii; if (keyToIndex(d, key, &idx)) { p = (Pair *)List_get((List *)d, idx); p->value = value; retVal = true; } else { p = new_Pair(key, value); added = false; if (List_length((List *)d) > 0) { for (ii = 0; ii < List_length((List *)d); ++ii) { pp = (Pair *)List_get((List *)d, ii); if (strcmp(key, pp->key) < 0) { List_insert((List *)d, ii, p); added = true; break; } } } if (!added) retVal = List_append((List *)d, p); } Logging_tracef("++++ Added pointer 0x%x to Dict 0x%x", (unsigned int)value, (unsigned int)d); return retVal; }
/* all is an Oec_AList of DataObject entries */ oe_id Oed_Dispatcher_reg_group(T _this_, DataObjectList all, oe_time dur, bool consume, user_callback *match_handler, user_callback *timeout_handler, user_callback_arg args) { oe_id sid = 0; assert(all); List_T group = List_list(NULL); for (Iterator iter = DataObjectList_iterator(all, true); Iterator_hasMore(iter);) { DataObject o = Iterator_next(iter); oe_scalar *templ_p = DataObject_toArray(o); item_ *item = _create_reg_item(_this_, templ_p, dur, consume, match_handler, timeout_handler, args); sid = item->sid; group = List_append(group, List_list(item, NULL)); } item_ **groupitems = (item_**) List_toArray(group, NULL); for (int i = 0; i < List_length(group); i++) { groupitems[i]->group = group; _schedule_item(_this_, groupitems[i]); } Mem_free(groupitems, __FILE__, __LINE__); return sid; //you can cancel the whole group by unreg'ing this one sid }
/* Env variables are stored in the environment list as "name=value" strings */ void Command_setEnv(Command_T C, const char *name, const char *value) { assert(C); assert(name); removeEnv(C, name); List_append(C->env, Str_cat("%s=%s", name, value ? value : "")); FREE(C->_env); // Recreate Command environment on exec }
void Post_subscribeWantedCarTransist(Post_t self, void * receiver, PostEvent_CB cb, void * data){ Event_t event = (Event_t)malloc(sizeof(struct Event)); event->receiver = receiver; event->cb = cb; event->data = data; List_append(self->wantedCarEvents, event); }
List_t Post_getWantedCars(Post_t self){ int lSize = List_getSize(self->wantedCars); List_t retList = List_new(); for(int i = 0; i < lSize; i++){ List_append(retList, List_get(self->wantedCars, i, NULL)); } return retList; }
List_t Post_getTransists(Post_t self){ int lSize = List_getSize(self->transists); List_t retList = List_new(); for(int i = 0; i < lSize; i++){ List_append(retList, List_get(self->transists, i, NULL)); } return retList; }
/** Removes "." and ".." from a path */ char *getCanonicalPath(const char *path){ char *prefix = NULL; char *rest = NULL; char *tmp = NULL; size_t offset = 0; char **src = NULL; List *dst = NULL; size_t ii = 0; Buffer *buf = NULL; char *result = NULL; if (path != NULL && strlen(path) > 0) { tmp = strxreplace(astrcpy(path), '\\', '/'); if (isDosPath(tmp) || isUncPath(tmp)) { if (isDosPath(tmp)) { prefix = getPathPart(tmp, PATH_DRIVE); offset = 0; } else if (isUncPath(tmp)) { prefix = getPathPart(tmp, PATH_HOST); offset = 2; } rest = astrcpy(strchr(&tmp[offset], '/')); } else { rest = astrcpy(tmp); } src = astrtok(rest, "/"); dst = new_List(); while (src[ii] != NULL) { if (strxequals(src[ii], "..")) { List_remove(dst, -1, false); } else if (!strxequals(src[ii], ".")) { List_append(dst, src[ii]); } ii++; } buf = new_Buffer(0); if (prefix != NULL) { Buffer_appendString(buf, prefix); } for (ii = 0; ii < List_length(dst); ++ii) { Buffer_appendString(buf, List_get(dst, ii)); if (ii != (List_length(dst) - 1)) { Buffer_appendChar(buf, '/'); } } result = astrcpy(buf->data); delete_Buffer(buf); delete_List(dst, false); astrtokfree(src); mu_free(prefix); mu_free(rest); mu_free(tmp); } return result; }
Errors EntryList_appendCString(EntryList *entryList, EntryTypes type, const char *pattern, PatternTypes patternType ) { EntryNode *entryNode; #if defined(PLATFORM_LINUX) #elif defined(PLATFORM_WINDOWS) String string; #endif /* PLATFORM_... */ Errors error; assert(entryList != NULL); assert(pattern != NULL); // allocate entry node entryNode = LIST_NEW_NODE(EntryNode); if (entryNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } entryNode->type = type; entryNode->string = String_newCString(pattern); // init pattern #if defined(PLATFORM_LINUX) error = Pattern_initCString(&entryNode->pattern, pattern, patternType, PATTERN_FLAG_NONE ); #elif defined(PLATFORM_WINDOWS) // escape all '\' by '\\' string = String_newCString(pattern); String_replaceAllCString(string,STRING_BEGIN,"\\","\\\\"); error = Pattern_init(&entryNode->pattern, string, patternType, PATTERN_FLAG_IGNORE_CASE ); // free resources String_delete(string); #endif /* PLATFORM_... */ if (error != ERROR_NONE) { String_delete(entryNode->string); LIST_DELETE_NODE(entryNode); return error; } // add to list List_append(entryList,entryNode); return ERROR_NONE; }
List_t Post_getLastNCars(Post_t self, unsigned int N){ int lSize = List_getSize(self->transists); if (N >= lSize) printf("Post: invalid index %d", N); List_t retList = List_new(); for(int i = lSize - N; i < lSize; i++){ List_append(retList, Transist_getCar(List_get(self->transists, i, NULL))); } return retList; }
//Register an object as a handler for events void EH_registerHandler(Rect touchableArea, EventHandler evHan, bool needsNotification, void* selfRef) { if(!isInitialised) EH_init(); EventHandlingObject obj; obj.touchableArea = touchableArea; obj.evHandler = evHan; obj.needsNoActionNotification = needsNotification; obj.selfRef = selfRef; List_append(&EventHandlers, &obj); }
void fire_callback(int delay) { if (player_firing) { Bullet* b; b = Player_fire(game->player); if (b != NULL) { List_append(game->bullets, (void*) b); } glutTimerFunc(delay, fire_callback, delay); } }
void Tree_add_child(Node *parent, Node *child) { List *list = parent->list; if(list==NULL) { list = List_create(); parent->list = list; } List_append(list, child); child->parent = parent; }
List_t Post_getCars(Post_t self, TRANSIST_DEST dest){ int lSize = List_getSize(self->transists); List_t retList = List_new(); for(int i = 0; i < lSize; i++){ Transist_t transist = List_get(self->transists, i, NULL); if(dest == transist->dest){ List_append(retList, Transist_getCar(transist)); } } return retList; }
int main() { List_t list = List_new(); List_append(list, "1"); List_append(list, "-2"); List_append(list, "3"); List_append(list, "-1.2"); List_append(list, "1.1"); procSequence(list, accmulateSumInt, accmulateSumDouble); procSequence(list, accmulateAbsSumInt, accmulateAbsSumDouble); printf("%d\n", accmulateSumInt(0)); printf("%f\n\n", accmulateSumDouble(0)); printf("%d\n", accmulateAbsSumInt(0)); printf("%f", accmulateAbsSumDouble(0)); List_delete(list); return 0; }
/* * _metric_list * * Output list of all available metrics */ static void _metric_list(void) { const char *func = __FUNCTION__; cerebro_namelist_t m = NULL; cerebro_namelist_iterator_t mitr = NULL; List l = NULL; ListIterator litr = NULL; char *str; if (!(m = cerebro_get_metric_names(handle))) { char *msg = cerebro_strerror(cerebro_errnum(handle)); _clean_err_exit(cerebro_errnum(handle)); err_exit("%s: cerebro_get_metric_names: %s", func, msg); } if (!(mitr = cerebro_namelist_iterator_create(m))) { char *msg = cerebro_strerror(cerebro_namelist_errnum(m)); err_exit("%s: cerebro_namelist_iterator_create: %s", func, msg); } l = List_create(NULL); while (!cerebro_namelist_iterator_at_end(mitr)) { if (cerebro_namelist_iterator_name(mitr, &str) < 0) { char *msg = cerebro_strerror(cerebro_namelist_iterator_errnum(mitr)); err_exit("%s: cerebro_namelist_iterator_name: %s", func, msg); } List_append(l, str); if (cerebro_namelist_iterator_next(mitr) < 0) { char *msg = cerebro_strerror(cerebro_namelist_iterator_errnum(mitr)); err_exit("%s: cerebro_namelist_iterator_next: %s", func, msg); } } litr = List_iterator_create(l); while ((str = list_next(litr))) fprintf(stdout, "%s\n", str); /* List_destroy() and cerebro_namelist_destory() destroy iterators too */ List_destroy(l); (void)cerebro_namelist_destroy(m); }
T Command_new(const char *path, const char *arg0, ...) { T C; if (! File_exist(path)) THROW(AssertException, "File '%s' does not exist", path ? path : "null"); NEW(C); C->env = List_new(); C->args = List_new(); List_append(C->env, Str_dup(Command_Path)); va_list ap; va_start(ap, arg0); buildArgs(C, path, arg0, ap); va_end(ap); return C; }
void Post_pass(Post_t self, Transist_t transist){ if(Post_carIsWanted(self, transist->car->id)){ int lSize = List_getSize(self->wantedCarEvents); for(int i = 0; i < lSize; i++){ Event_t ev = List_get(self->wantedCarEvents, i, NULL); if(ev->cb != NULL){ PostEvent_CB fn = ev->cb; fn(ev->receiver, self, ev->data); break; } } } List_append(self->transists, transist); }
/** *** \brief Stores a value in the dictionary with the specified key. *** *** If a value with that key already exists in the dictionary, it will be *** replaced with the new value. *** \note This is a potential memory leak! **/ bool Dict_put(Dict *d, const char *key, void *value) { bool retVal = false; size_t idx = 0; Pair *p = NULL; if(keyToIndex(d, key, &idx)){ p = (Pair *)List_get((List *)d, idx); p->value = value; retVal = true; } else{ p = new_Pair(key, value); retVal = List_append((List *)d, p); } Logging_tracef("++++ Added pointer 0x%x to Dict 0x%x", (unsigned int)value, (unsigned int)d); return retVal; }
T Command_new(const char *path, const char *arg0, ...) { T C; assert(path); if (! File_exist(path)) THROW(AssertException, "File '%s' does not exist", path); NEW(C); C->env = List_new(); C->args = List_new(); va_list ap; va_start(ap, arg0); buildArgs(C, path, arg0, ap); va_end(ap); // Copy this process's environment for transit to sub-processes extern char **environ; for (char **e = environ; *e; e++) { List_append(C->env, Str_dup(*e)); } return C; }
FileFragmentNode *FileFragmentList_addFile(FileFragmentList *fileFragmentList, const String fileName, uint64 size) { FileFragmentNode *fileFragmentNode; assert(fileFragmentList != NULL); assert(fileName != NULL); fileFragmentNode = LIST_NEW_NODE(FileFragmentNode); if (fileFragmentNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } fileFragmentNode->fileName = String_duplicate(fileName); fileFragmentNode->size = size; List_init(&fileFragmentNode->fragmentList); List_append(fileFragmentList,fileFragmentNode); return fileFragmentNode; }
void List_test(void) { List *np, *head = NULL; int i; for (i = 0; i < 10; i++) { List_append(&head, (void *)i); } np = head; for (i = 0; i < 10; i++) { assert((int)np->data == i); np = np->next; } List_free(&head, NULL); // make sure free empty list doesn't choke head = NULL; List_free(&head, NULL); printf("%s: All tests pass.\n", __FILE__); }
/** * \brief Get a list of sources * * Get a list of sources available. Each item in the list is a string giving the * name of the source prefixed with either "c:" or "s:" for client and server * sources respectively. * * \return List of sources */ List* SVR_getSourcesList(void) { List* sources_list; SVR_Message* message; SVR_Message* response; message = SVR_Message_new(1); message->components[0] = SVR_Arena_strdup(message->alloc, "Source.getSourcesList"); response = SVR_Comm_sendMessage(message, true); sources_list = List_new(); for(int i = 1; i < response->count; i++) { List_append(sources_list, strdup(response->components[i])); } SVR_Message_release(message); SVR_Message_release(response); return sources_list; }
void cerebrod_queue_event(struct cerebro_event *event, unsigned int index) { struct cerebrod_event_to_send *ets; assert(event); assert(event_queue); Pthread_mutex_lock(&event_queue_lock); ets = (struct cerebrod_event_to_send *)Malloc(sizeof(struct cerebrod_event_to_send)); ets->event_name = event->event_name; ets->index = index; ets->event = event; List_append(event_queue, ets); Pthread_cond_signal(&event_queue_cond); Pthread_mutex_unlock(&event_queue_lock); }
FragmentNode *FragmentList_add(FragmentList *fragmentList, const String name, uint64 size, const void *userData, uint userDataSize ) { FragmentNode *fragmentNode; assert(fragmentList != NULL); assert(name != NULL); fragmentNode = LIST_NEW_NODE(FragmentNode); if (fragmentNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } fragmentNode->name = String_duplicate(name); fragmentNode->size = size; if (userData != NULL) { fragmentNode->userData = malloc(userDataSize); if (fragmentNode->userData == NULL) { HALT_INSUFFICIENT_MEMORY(); } memcpy(fragmentNode->userData,userData,userDataSize); fragmentNode->userDataSize = userDataSize; } else { fragmentNode->userData = NULL; fragmentNode->userDataSize = 0; } List_init(&fragmentNode->fragmentEntryList); List_append(fragmentList,fragmentNode); return fragmentNode; }
FragmentNode *FragmentList_add(FragmentList *fragmentList, const String name, uint64 size, const void *userData, uint userDataSize ) { FragmentNode *fragmentNode; assert(fragmentList != NULL); assert(name != NULL); fragmentNode = LIST_NEW_NODE(FragmentNode); if (fragmentNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } FragmentList_initNode(fragmentNode,name,size,userData,userDataSize); List_append(fragmentList,fragmentNode); return fragmentNode; }
/* * _event_node_timeout_data_add * * Create entries for the event_node_timeout_data list and index * * Returns 0 on success, -1 on error */ static int _event_node_timeout_data_add(const char *nodename, u_int32_t time_now) { struct cerebrod_event_node_timeout_data *ntd; #if CEREBRO_DEBUG int rv; /* Should be called with lock already set */ rv = Pthread_mutex_trylock(&event_node_timeout_data_lock); if (rv != EBUSY) CEREBROD_EXIT(("mutex not locked: rv=%d", rv)); #endif /* CEREBRO_DEBUG */ ntd = (struct cerebrod_event_node_timeout_data *)Malloc(sizeof(struct cerebrod_event_node_timeout_data)); ntd->nodename = (char *)nodename; ntd->last_received_time = time_now; ntd->timeout_occurred = 0; List_append(event_node_timeout_data, ntd); Hash_insert(event_node_timeout_data_index, ntd->nodename, ntd); event_node_timeout_data_index_numnodes++; return 0; }
Errors PatternList_appendCString(PatternList *patternList, const char *pattern, PatternTypes patternType ) { PatternNode *patternNode; Errors error; assert(patternList != NULL); assert(pattern != NULL); // allocate pattern node patternNode = LIST_NEW_NODE(PatternNode); if (patternNode == NULL) { HALT_INSUFFICIENT_MEMORY(); } patternNode->string = String_newCString(pattern); // init pattern error = Pattern_initCString(&patternNode->pattern, pattern, patternType, PATTERN_FLAG_IGNORE_CASE ); if (error != ERROR_NONE) { String_delete(patternNode->string); LIST_DELETE_NODE(patternNode); return error; } // add to list List_append(patternList,patternNode); return ERROR_NONE; }
static void quick_sort(List *l, /*List_Iterator *first, List_Iterator *last,*/ list_cmp_fct cmpf) { /* A LITTLE MORE OPTIMIZED BUT BUGGED VERSION List_Iterator *pivot = last; List_Iterator *it = first; List_Iterator *next = NULL; void *data = NULL; last = NULL; if (!it || !pivot || it == pivot || !pivot->prev || !it->next) { return; } while (it != pivot) { next = it->next; if (cmpf(it->data, pivot->data) <= 0) { if (it == first) first = it->next; data = List_remove_it(l, it); assert(data); assert(List_insert_after_it(l, pivot, data)); if (last == NULL) last = pivot->next; } it = next; } quick_sort(l, first, pivot->prev, cmpf); quick_sort(l, pivot->next, last, cmpf);*/ void *pivot; int cmp = 0; List *less = NEW(List); List *greater = NEW(List); List *equal = NEW(List); List_Iterator *it; if (!less || !greater || !equal) { perror("malloc"); return ; } if (COUNT(l) <= 1) return ; it = List_get_it(l, (COUNT(l)/2 - 1)); pivot = it->data; List_remove_it(l, it); while (COUNT(l)) { it = List_pop_first_it(l); cmp = cmpf(it->data, pivot); if (cmp > 0) List_append_it(less, it); else if (cmp < 0) List_append_it(greater, it); else List_append_it(equal, it); } // SUBLISTS if (COUNT(less)) { quick_sort(less, cmpf); List_concat(l, less); } else free(less); // List_append(l, pivot); if (COUNT(equal)) { List_concat(l, equal); } else free(equal); if (COUNT(greater)) { quick_sort(greater, cmpf); List_concat(l, greater); } else free(greater); }
/* * _setup_metric_modules * * Setup metric modules. Under almost any circumstance, don't return a * -1 error, cerebro can go on without loading metric modules. * * Returns 1 if modules are loaded, 0 if not, -1 on error */ static int _setup_metric_modules(void) { int i; #if CEREBRO_DEBUG #if !WITH_CEREBROD_NO_THREADS int rv; #endif /* !WITH_CEREBROD_NO_THREADS */ #endif /* CEREBRO_DEBUG */ assert(metric_list); #if CEREBRO_DEBUG #if !WITH_CEREBROD_NO_THREADS /* Should be called with lock already set */ rv = Pthread_mutex_trylock(&metric_list_lock); if (rv != EBUSY) CEREBRO_EXIT(("mutex not locked: rv=%d", rv)); #endif /* !WITH_CEREBROD_NO_THREADS */ #endif /* CEREBRO_DEBUG */ if (!(metric_handle = metric_modules_load())) { CEREBRO_DBG(("metric_modules_load")); goto cleanup; } if ((metric_handle_count = metric_modules_count(metric_handle)) < 0) { CEREBRO_DBG(("metric_module_count failed")); goto cleanup; } if (!metric_handle_count) { #if CEREBRO_DEBUG if (conf.debug && conf.speak_debug) { #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_lock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ fprintf(stderr, "**************************************\n"); fprintf(stderr, "* No Metric Modules Found\n"); fprintf(stderr, "**************************************\n"); #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_unlock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ } #endif /* CEREBRO_DEBUG */ goto cleanup; } for (i = 0; i < metric_handle_count; i++) { struct cerebrod_speaker_metric_info *metric_info; #if !WITH_CEREBROD_NO_THREADS Cerebro_metric_thread_pointer threadPtr; #endif /* !WITH_CEREBROD_NO_THREADS */ char *module_name, *metric_name; int metric_period; u_int32_t metric_flags; module_name = metric_module_name(metric_handle, i); if (conf.metric_module_exclude_len) { int found_exclude = 0; int j; for (j = 0; j < conf.metric_module_exclude_len; j++) { if (!strcasecmp(conf.metric_module_exclude[j], module_name)) { found_exclude++; break; } } if (found_exclude) { #if CEREBRO_DEBUG if (conf.debug && conf.speak_debug) { #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_lock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ fprintf(stderr, "**************************************\n"); fprintf(stderr, "* Skip Metric Module: %s\n", module_name); fprintf(stderr, "**************************************\n"); #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_unlock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ } #endif /* CEREBRO_DEBUG */ CEREBRO_ERR(("Dropping metric module: %s", module_name)); continue; } } #if CEREBRO_DEBUG if (conf.debug && conf.speak_debug) { #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_lock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ fprintf(stderr, "**************************************\n"); fprintf(stderr, "* Setup Metric Module: %s\n", module_name); fprintf(stderr, "**************************************\n"); #if !WITH_CEREBROD_NO_THREADS Pthread_mutex_unlock(&debug_output_mutex); #endif /* !WITH_CEREBROD_NO_THREADS */ } #endif /* CEREBRO_DEBUG */ if (metric_module_setup(metric_handle, i) < 0) { CEREBRO_DBG(("metric_module_setup: %s", module_name)); continue; } if (!(metric_name = metric_module_get_metric_name(metric_handle, i))) { CEREBRO_DBG(("metric_module_get_metric_name: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } if (metric_module_get_metric_period(metric_handle, i, &metric_period) < 0) { CEREBRO_DBG(("metric_module_get_metric_period: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } if (metric_module_get_metric_flags(metric_handle, i, &metric_flags) < 0) { CEREBRO_DBG(("metric_module_get_metric_flags: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } if (metric_flags & CEREBRO_METRIC_MODULE_FLAGS_SEND_ON_PERIOD && metric_period <= 0) { CEREBRO_DBG(("metric module period invalid: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } if (metric_module_send_message_function_pointer(metric_handle, i, &cerebrod_send_message) < 0) { CEREBRO_DBG(("metric_module_send_message_function_pointer: %s", module_name)); metric_module_cleanup(metric_handle, i); continue; } metric_info = Malloc(sizeof(struct cerebrod_speaker_metric_info)); /* No need to Strdup() the name in this case */ metric_info->metric_name = metric_name; metric_info->metric_origin = CEREBROD_METRIC_SPEAKER_ORIGIN_MODULE; metric_info->metric_period = metric_period; metric_info->metric_flags = metric_flags; metric_info->index = i; /* * If metric period is < 0, it presumably never will be sent * (metric is likely handled by a metric_thread), so set * next_call_time to UINT_MAX. * * If this is a metric that will be piggy-backed on heartbeats, * then initialize next_call_time to 0, so the data is sent on * the first heartbeat * * If this is a metric that will not be piggy-backed on * heartbeats, set the next_call_time to UINT_MAX. Let the * speaker logic decide when packets should be sent. */ if (metric_info->metric_period < 0 || metric_info->metric_flags & CEREBRO_METRIC_MODULE_FLAGS_SEND_ON_PERIOD) metric_info->next_call_time = UINT_MAX; else metric_info->next_call_time = 0; List_append(metric_list, metric_info); metric_list_size++; #if !WITH_CEREBROD_NO_THREADS if ((threadPtr = metric_module_get_metric_thread(metric_handle, i))) { pthread_t thread; pthread_attr_t attr; Pthread_attr_init(&attr); Pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); Pthread_attr_setstacksize(&attr, CEREBROD_THREAD_STACKSIZE); Pthread_create(&thread, &attr, threadPtr, NULL); Pthread_attr_destroy(&attr); } #endif /* !WITH_CEREBROD_NO_THREADS */ } if (!metric_list_size) goto cleanup; cerebrod_speaker_data_metric_list_sort(); return 1; cleanup: if (metric_handle) { /* unload will call module cleanup functions */ metric_modules_unload(metric_handle); metric_handle = NULL; metric_handle_count = 0; } metric_list_size = 0; return 0; }