mutex: more random sleeps

This commit is contained in:
PowerUser64 2024-11-25 22:41:22 -08:00
parent 1043680b19
commit 160d22ded8

View file

@ -3,8 +3,8 @@
* @author Blake North <blake.north@digipen.edu>
*/
#include <cstddef> // size_t
#include <cstring> // memset
#include <cstddef> // size_t
#include <cstring> // memset
#include <ctime>
#include <iostream> // cout
#include <vector> // vector
@ -13,8 +13,11 @@
#include <pthread.h> // pthread
#include <unistd.h> // 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<int *>(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<PthreadFun>(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;