Skip to content

Instantly share code, notes, and snippets.

@Micrified
Created August 31, 2020 15:40
Show Gist options
  • Save Micrified/33ba4b48d3c2e8ab5c1a2fc25cae0b91 to your computer and use it in GitHub Desktop.
Save Micrified/33ba4b48d3c2e8ab5c1a2fc25cae0b91 to your computer and use it in GitHub Desktop.
Preemptive Threading Demo
#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);
}
// Print
{
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