ИУП: интенсив 7 дней + диагностический пакет (32 вопроса, 9 задач с автопроверкой)
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
#include <cstdio>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include "solution.cpp"
|
||||
|
||||
static int failures = 0;
|
||||
#define CHECK(cond, name) do { if (cond) std::printf("ok %s\n", name); \
|
||||
else { std::printf("FAIL %s (line %d)\n", name, __LINE__); ++failures; } } while (0)
|
||||
|
||||
int main() {
|
||||
// Базовая дисциплина
|
||||
{
|
||||
BlockingQueue q(2);
|
||||
q.push(1);
|
||||
q.push(2);
|
||||
CHECK(q.size() == 2, "size() == 2 после двух push");
|
||||
int v = 0;
|
||||
CHECK(q.pop(v) && v == 1, "pop -> 1 (FIFO)");
|
||||
CHECK(q.pop(v) && v == 2, "pop -> 2 (FIFO)");
|
||||
q.close();
|
||||
CHECK(!q.pop(v), "после close и опустошения pop -> false");
|
||||
bool threw = false;
|
||||
try { q.push(3); } catch (const std::runtime_error&) { threw = true; }
|
||||
CHECK(threw, "push после close -> std::runtime_error");
|
||||
}
|
||||
// Продюсеры/потребители под нагрузкой
|
||||
{
|
||||
const int P = 4, C = 4, PER = 20000, C3 = 64;
|
||||
BlockingQueue q(C3);
|
||||
std::atomic<int> pushed{0};
|
||||
std::atomic<long long> sum{0};
|
||||
std::atomic<int> popped{0};
|
||||
std::atomic<int> over{0};
|
||||
|
||||
auto producer = [&](int pid) {
|
||||
for (int i = 0; i < PER; ++i) {
|
||||
q.push(pid * 1000000 + i);
|
||||
pushed.fetch_add(1, std::memory_order_relaxed);
|
||||
if (q.size() > C3) over.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
};
|
||||
auto consumer = [&](int) {
|
||||
int v = 0;
|
||||
while (q.pop(v)) {
|
||||
sum.fetch_add(v, std::memory_order_relaxed);
|
||||
popped.fetch_add(1, std::memory_order_relaxed);
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<std::thread> ts;
|
||||
for (int i = 0; i < C; ++i) ts.emplace_back(consumer, i);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
for (int i = 0; i < P; ++i) ts.emplace_back(producer, i);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
while (pushed.load() < P * PER) std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
q.close();
|
||||
for (auto& t : ts) t.join();
|
||||
|
||||
long long expect = 0;
|
||||
for (int p = 0; p < P; ++p) for (int i = 0; i < PER; ++i) expect += (long long)p * 1000000 + i;
|
||||
std::printf(" (вставлено=%d, извлечено=%d, переполнений=%d)\n",
|
||||
pushed.load(), popped.load(), over.load());
|
||||
CHECK(pushed.load() == P * PER, "все вставки выполнены (нет потерь)");
|
||||
CHECK(popped.load() == P * PER, "извлечено ровно столько же (нет дублей/потерь)");
|
||||
CHECK(sum.load() == expect, "сумма значений совпадает с эталоном");
|
||||
CHECK(over.load() == 0, "size() не превышал capacity");
|
||||
}
|
||||
std::printf(failures ? "\nFAILURES: %d\n" : "\nALL PASS\n", failures);
|
||||
return failures ? 1 : 0;
|
||||
}
|
||||
Reference in New Issue
Block a user