static int ds_btree_bf_iterate(struct _ds_btree **btreep, ds_btree_func func, void *user_data) { struct _ds_btree *btree = *btreep; ds_queue *queue; if (!btree) return 0; queue = ds_queue_alloc(); if (!queue) return -ENOMEM; ds_queue_enqueue(queue, btree); while (!ds_queue_empty(queue)) { btree = ds_queue_dequeue(queue); func((void *)btree->btree_data, user_data); if (btree->left) ds_queue_enqueue(queue, btree->left); if (btree->right) ds_queue_enqueue(queue, btree->right); } ds_queue_free(queue); return 0; }
int main(void) { struct DSQueue *job_queue, *results_queue; pthread_t *producers, *consumers; struct job *prod_jobs, *cons_jobs; int i; int *result, result_sum; if (SEQUENTIAL) { sequential(); exit(0); } /* If there is a bad value from sysconf, just assume 1. */ cpus = (int) sysconf(_SC_NPROCESSORS_ONLN); cpus = cpus == 0 ? 1 : cpus; /* Compute the number of producer/consumer threads to start. */ num_producers = num_producers == 0 ? cpus : num_producers; num_consumers = num_consumers == 0 ? cpus : num_consumers; /* Initialize thread safe queues. `job_queue` has a capacity equivalent * to the buffer size set by the user. `results_queue` always has a capacity * equivalent to the number of consumer threads so that every consumer * can send a value to `results_queue` without blocking. */ job_queue = ds_queue_create(BUFFER); results_queue = ds_queue_create(num_consumers); assert(producers = malloc(num_producers * sizeof(*producers))); assert(consumers = malloc(num_consumers * sizeof(*consumers))); assert(prod_jobs = malloc(num_producers * sizeof(*prod_jobs))); assert(cons_jobs = malloc(num_consumers * sizeof(*cons_jobs))); /* Create `num_producers` jobs and threads. * Similarly for `num_consumers`. */ for (i = 0; i < num_producers; i++) { prod_jobs[i] = job_create(i, job_queue, results_queue); pthread_create(&(producers[i]), NULL, producer, (void*) &(prod_jobs[i])); } for (i = 0; i < num_consumers; i++) { cons_jobs[i] = job_create(i, job_queue, results_queue); pthread_create(&(consumers[i]), NULL, consumer, (void*) &(cons_jobs[i])); } /* Wait for all of the producers to finish producing. */ for (i = 0; i < num_producers; i++) assert(0 == pthread_join(producers[i], NULL)); /* Now that the producers are done, no more values will be sent to * `job_queue`, and therefore, it should be closed. (Values can still * be read from a closed queue.) */ ds_queue_close(job_queue); /* Free the producer jobs. */ for (i = 0; i < num_producers; i++) free(prod_jobs[i].id); free(prod_jobs); /* Now wait for the consumers to finish consuming. */ for (i = 0; i < num_consumers; i++) assert(0 == pthread_join(consumers[i], NULL)); /* Now that the consumers are done, no more values will be sent to * `results_queue`, and therefore, it should be closed. */ ds_queue_close(results_queue); /* Free the consumer jobs. */ for (i = 0; i < num_consumers; i++) free(cons_jobs[i].id); free(cons_jobs); /* Read all values in `results_queue`, and sum them up to get the total * number of consumed items. */ result_sum = 0; while (NULL != (result = (int*) ds_queue_pop(results_queue))) { result_sum += *result; free(result); } /* Print out the total number of produced and consumed items. * In this example, these numbers should always be equal. * N.B. Watch out for integer division! */ printf("Total produced: %d\n", (JOBS / num_producers) * num_producers); printf("Total consumed: %d\n", result_sum); free(consumers); free(producers); ds_queue_free(job_queue); ds_queue_free(results_queue); return 0; }
static void ds_queue_free_object(zend_object *object) { php_ds_queue_t *q = (php_ds_queue_t*) object; zend_object_std_dtor(&q->std); ds_queue_free(q->queue); }