Parent directory
Makefile
concur.cpp
cond-var.cpp
pthread.cpp
CC = g++
CXX = g++
CFLAGS = -Wall -g
CXXFLAGS = -Wall -g -std=c++20 -pthread
LDFLAGS = -pthread
LDLIBS =
executables = pthread concur cond-var
.PHONY: default
default: $(executables)
pthread: pthread.o
concur: concur.o
cond-var: cond-var.o
.PHONY: clean
clean:
rm -f a.out core *.o $(executables)
.PHONY: all
all: clean default#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace std::chrono;
struct wallet {
mutex m;
uint64_t money = 0;
operator uint64_t() const { return money; }
wallet& operator++() {
m.lock();
++money;
m.unlock();
// {
// scoped_lock lck{m};
// ++money;
// }
return *this;
}
};
void f(wallet& sum, uint64_t count) {
while (count--) {
++sum;
}
}
int main() {
constexpr uint64_t count = 1'000'000;
wallet sum;
auto time0 = high_resolution_clock::now();
thread t1 { f, ref(sum), count };
thread t2 { f, ref(sum), count };
t1.join();
t2.join();
// {
// jthread t1 { f, ref(sum), 1'000'000 };
// jthread t2 { f, ref(sum), 1'000'000 };
// }
auto time1 = high_resolution_clock::now();
auto dt = duration_cast<microseconds>(time1 - time0);
cout << "elapsed: " << dt.count() << " microsec\n";
cout << "result: " << sum << '\n';
}
/*
Lecture outline:
1. std::thread and std::mutex
2. std::scoped_lock
3. std::jthread
*/#include <iostream>
#include <sstream>
#include <algorithm>
#include <cstdlib>
#include <cassert>
#include <random>
#include <thread>
#include <deque>
#include <mutex>
#include <condition_variable>
using namespace std;
int main() {
vector<string> vec;
mutex mtx;
condition_variable got_something;
thread t {
[&]() {
while (1) {
unique_lock lck(mtx); // lck's contructor will lock mtx
while (vec.empty()) {
got_something.wait(lck); // wait will release lck
}
// lck is reacquired when wait() returns
for (const auto& x : vec) {
// exit thread on poison value
if (x == ""s) {
return;
}
cout << x << ' ';
}
cout << '\n';
vec.clear();
// lck's destructor will unlock mtx
}
}
};
string str, line;
while (getline(cin, line)) {
istringstream iss(line);
unique_lock lck(mtx); // lck's contructor will lock mtx
while (iss >> str) { vec.push_back(str); }
got_something.notify_one(); // unblock one waiting thread
// lck's destructor will unlock mtx
}
{
unique_lock lck(mtx);
vec.push_back(""s); // poison value to tell the thread to exit
got_something.notify_one();
}
t.join();
}#include <iostream>
#include <chrono>
#include <pthread.h>
using namespace std;
using namespace std::chrono;
struct Args {
uint64_t* sum_ptr;
uint64_t count;
};
void* f1(void* args) {
Args* p = (Args*)args;
uint64_t* sum_ptr = p->sum_ptr;
uint64_t count = p->count;
while (count--) {
++*sum_ptr;
}
return NULL;
}
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
void* f2(void* args) {
Args* p = (Args*)args;
uint64_t* sum_ptr = p->sum_ptr;
uint64_t count = p->count;
while (count--) {
pthread_mutex_lock(&mtx);
++*sum_ptr;
pthread_mutex_unlock(&mtx);
}
return NULL;
}
uint64_t sum1() {
constexpr uint64_t count = 1'000'000;
uint64_t sum = 0;
Args args1 { &sum, count };
f1(&args1);
Args args2 { &sum, count };
f1(&args2);
return sum;
}
uint64_t sum2() {
constexpr uint64_t count = 1'000'000;
uint64_t sum = 0;
pthread_t t1, t2;
Args args1 { &sum, count };
pthread_create(&t1, NULL, &f1, &args1);
Args args2 { &sum, count };
pthread_create(&t2, NULL, &f1, &args2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return sum;
}
uint64_t sum3() {
constexpr uint64_t count = 1'000'000;
uint64_t sum[2] = {0};
pthread_t t1, t2;
Args args1 { &sum[0], count };
pthread_create(&t1, NULL, &f1, &args1);
Args args2 { &sum[1], count };
pthread_create(&t2, NULL, &f1, &args2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return sum[0] + sum[1];
}
uint64_t sum4() {
constexpr uint64_t count = 1'000'000;
uint64_t sum[9] = {0};
pthread_t t1, t2;
Args args1 { &sum[0], count };
pthread_create(&t1, NULL, &f1, &args1);
Args args2 { &sum[8], count };
pthread_create(&t2, NULL, &f1, &args2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return sum[0] + sum[8];
}
uint64_t sum5() {
constexpr uint64_t count = 1'000'000;
uint64_t sum = 0;
pthread_t t1, t2;
Args args1 { &sum, count };
pthread_create(&t1, NULL, &f2, &args1);
Args args2 { &sum, count };
pthread_create(&t2, NULL, &f2, &args2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return sum;
}
int main() {
auto time0 = high_resolution_clock::now();
uint64_t result = sum1();
// uint64_t result = sum2();
// uint64_t result = sum3();
// uint64_t result = sum4();
// uint64_t result = sum5();
auto time1 = high_resolution_clock::now();
auto dt = duration_cast<microseconds>(time1 - time0);
cout << "elapsed: " << dt.count() << " microsec\n";
cout << "result: " << result << '\n';
}