diff --git a/main.cpp b/main.cpp index cb765cf..d17dac0 100644 --- a/main.cpp +++ b/main.cpp @@ -3,8 +3,8 @@ * @author Blake North */ -#include // size_t -#include // memset +#include // size_t +#include // memset #include #include // cout #include // vector @@ -13,8 +13,11 @@ #include // pthread #include // sleep() - testing +#define THREAD_LOOP_COUNT 10 #define NUM_THREADS 8 +#define SLEEP usleep(rand() % 50) // random sleep delay + typedef void *(*ThreadTask)(const struct thread_data &); typedef void *(*PthreadFun)(void *arg); @@ -39,51 +42,67 @@ struct thread_data { void *thread_task_increment(const struct thread_data &thread) { // exists inside the loop - const size_t max_loops = 10; + SLEEP; + const size_t max_loops = THREAD_LOOP_COUNT; + + SLEEP; size_t loops = 0; + SLEEP; + std::cout << "Hello from thread " << thread.id << "! (before run loop)" << std::endl; + SLEEP; + // thread loop, with an exit condition while (!(*thread.is_finished)) { + SLEEP; + // non-mutex operations { std::cout << "Hello from thread " << thread.id << "! (inside run loop, before mutex)" << std::endl; } - usleep(rand() % 200); + SLEEP; // mutex { // wait for permission to ask for the mutex while (!*thread.can_ask_for_mutex) - ; + SLEEP; + SLEEP; // say we want the mutex (*thread.wants_mutex) = true; - usleep(rand() % 200); + SLEEP; // block until we have the mutex while (!*thread.has_mutex) - ; + SLEEP; // enter the mutex std::cout << "Hello from thread " << thread.id << "! (inside run loop, inside mutex)" << std::endl; - usleep(rand() % 200); + SLEEP; + // increment the int (requires casting from void*) *static_cast(thread.data) += 1; + SLEEP; + // tell the thread manager we don't need the mutex (*thread.wants_mutex) = false; + SLEEP; // mutex exit } loops++; - if (max_loops < loops) + if (max_loops < loops) { + SLEEP; (*thread.is_finished) = true; + } } std::cout << "Hello from thread " << thread.id << "! (done)" << std::endl; @@ -129,11 +148,11 @@ void do_threading(struct thread_group threads) { // spawn threads (none will enter the mutex yet) for (size_t tid = 0; tid < threads.total_threads; ++tid) { - usleep(rand() % 200); + SLEEP; pthread_create(&my_pthreads[tid], NULL, reinterpret_cast(thread_task_increment), &thread_data[tid]); - usleep(rand() % 200); + SLEEP; } std::cout << "Threads have been spawned." << std::endl; @@ -141,40 +160,42 @@ void do_threading(struct thread_group threads) { // loop until all threads are done for (size_t finished_threads = 0; finished_threads < threads.total_threads;) { - usleep(rand() % 200); + SLEEP; // TODO: make sure we cycle the mutex through threads round-robin style // hand off the mutex to threads that want it for (size_t tid_wants = 0; tid_wants < threads.total_threads; ++tid_wants) { - usleep(rand() % 200); + SLEEP; if (threads.wants_mutex[tid_wants]) { // in case the mutex isn't used at all bool mutex_was_found = false; - usleep(rand() % 200); + SLEEP; // find which thread has the mutex and hand it off if it's done for (size_t tid_has = 0; tid_has < threads.total_threads; ++tid_has) { if (threads.has_mutex[tid_has]) { + + SLEEP; // we found who has the mutex! mutex_was_found = true; - usleep(rand() % 200); + SLEEP; // is the thread still using the mutex? if (!threads.wants_mutex[tid_has]) { - usleep(rand() % 200); + SLEEP; // take the mutex from the thread that has it threads.has_mutex[tid_has] = false; - usleep(rand() % 200); + SLEEP; threads.can_ask_for_mutex[tid_has] = true; - usleep(rand() % 200); + SLEEP; // give the mutex to the thread that wants it threads.can_ask_for_mutex[tid_wants] = false; - usleep(rand() % 200); + SLEEP; threads.has_mutex[tid_wants] = true; - usleep(rand() % 200); + SLEEP; } break; // no need to look at the rest if we found who has the mutex @@ -183,19 +204,22 @@ void do_threading(struct thread_group threads) { // give the thread the mutex if it wasn't found to be in use if (!mutex_was_found) { - usleep(rand() % 200); + SLEEP; threads.has_mutex[tid_wants] = true; + SLEEP; } - usleep(rand() % 200); + SLEEP; } } // find how many threads are done with the mutex finished_threads = 0; for (size_t tid = 0; tid < threads.total_threads; ++tid) { - if (threads.threads_finished[tid]) + if (threads.threads_finished[tid]) { finished_threads += 1; - usleep(rand() % 200); + SLEEP; + } + SLEEP; } } @@ -216,6 +240,8 @@ int main(void) { int count = 0; std::cout << "Pre: " << DBG_PRINT(count) << std::endl; + std::cout << "Expected: " << NUM_THREADS * (THREAD_LOOP_COUNT + 1) + count + << std::endl; mythreads.data = &count; mythreads.total_threads = NUM_THREADS;