Created
August 31, 2020 15:40
-
-
Save Micrified/33ba4b48d3c2e8ab5c1a2fc25cae0b91 to your computer and use it in GitHub Desktop.
Preemptive Threading Demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <thread> | |
#include <mutex> | |
#include <iostream> | |
#include <chrono> | |
#include <cstring> | |
#include <future> | |
#include <pthread.h> | |
#include <math.h> | |
// IO Access mutex | |
std::mutex g_mutex_io; | |
// Computation function (busy work) | |
static bool isPrime (unsigned int value) | |
{ | |
unsigned int i, root; | |
if (value == 1) return false; | |
if (value == 2) return true; | |
if ((value % 2) == 0) return false; | |
root = (int)(1.0 + sqrt(value)); | |
for (i = 3; (i < root) && (value % i != 0); i += 2); | |
return (i < root ? false : true); | |
} | |
// Thread function | |
void foo (unsigned int id, unsigned int count) | |
{ | |
sched_param sch; | |
int policy, sum = 0; | |
// Get information about thread | |
pthread_getschedparam(pthread_self(), &policy, &sch); | |
// Compute primes | |
for (unsigned int i = 1; i < count; ++i) { | |
sum += (isPrime(i) ? 1 : 0); | |
} | |
{ | |
std::lock_guard<std::mutex> lock(g_mutex_io); | |
std::cout << "Thread " << id << " computed " << sum << " primes" | |
<< " at priority level: " << sch.sched_priority << std::endl; | |
} | |
} | |
int main () | |
{ | |
sched_param sch; | |
int policy; | |
// Declare and init task objects | |
std::packaged_task<void(unsigned int, unsigned int)> task_1(foo); | |
std::packaged_task<void(unsigned int, unsigned int)> task_2(foo); | |
// Get the futures | |
auto task_fut_1 = task_1.get_future(); | |
auto task_fut_2 = task_2.get_future(); | |
// Declare and init thread objects | |
std::thread thread_1(std::move(task_1), 1, 50000000); | |
std::thread thread_2(std::move(task_2), 2, 50000000); | |
// Set first thread policy | |
pthread_getschedparam(thread_1.native_handle(), &policy, &sch); | |
sch.sched_priority = 97; | |
if (pthread_setschedparam(thread_1.native_handle(), SCHED_FIFO, &sch)) { | |
std::cerr << "pthread_setschedparam: " << std::strerror(errno) | |
<< std::endl; | |
return -1; | |
} | |
// Set second thread policy | |
pthread_getschedparam(thread_2.native_handle(), &policy, &sch); | |
sch.sched_priority = 98; | |
if (pthread_setschedparam(thread_2.native_handle(), SCHED_FIFO, &sch)) { | |
std::cerr << "pthread_setschedparam: " << std::strerror(errno) | |
<< std::endl; | |
return -1; | |
} | |
// Set main process thread priority | |
pthread_getschedparam(pthread_self(), &policy, &sch); | |
sch.sched_priority = 99; | |
if (pthread_setschedparam(pthread_self(), SCHED_FIFO, &sch)) { | |
std::cerr << "pthread_setschedparam: " << std::strerror(errno) | |
<< std::endl; | |
return -1; | |
} | |
// Detach these threads | |
thread_1.detach(); thread_2.detach(); | |
// Check their status with a timeout | |
for (int finished = 0; finished < 2; ) { | |
std::this_thread::sleep_for(std::chrono::seconds(1)); | |
{ | |
std::lock_guard<std::mutex> lock(g_mutex_io); | |
std::cout << "Main: Checking ..." << std::endl; | |
} | |
if (task_fut_1.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { | |
{ | |
std::lock_guard<std::mutex> lock(g_mutex_io); | |
std::cout << "Main: Task 1 has finished!" << std::endl; | |
} | |
finished++; | |
} | |
if (task_fut_1.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { | |
{ | |
std::lock_guard<std::mutex> lock(g_mutex_io); | |
std::cout << "Main: Task 2 has finished!" << std::endl; | |
} | |
finished++; | |
} | |
} | |
pthread_getschedparam(pthread_self(), &policy, &sch); | |
std::cout << "Main: Exiting at priority level: " << sch.sched_priority << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment