
6 changed files with 379 additions and 0 deletions
@ -0,0 +1,110 @@ |
|||||
|
// This file is under GNU General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#include <iostream> |
||||
|
#include <thread> |
||||
|
#include <cassert> |
||||
|
#include <pEp/std_utils.hh> |
||||
|
#include "../src/CountingSemaphore.hh" |
||||
|
|
||||
|
using namespace std; |
||||
|
using namespace pEp; |
||||
|
|
||||
|
thread make_two_threads_for_many_threads() |
||||
|
{ |
||||
|
thread res([&]() { |
||||
|
CountingSemaphore semaphore; |
||||
|
semaphore = 3; |
||||
|
|
||||
|
thread thread1([&]() { |
||||
|
semaphore.p (); |
||||
|
semaphore.p (); |
||||
|
semaphore.p (); |
||||
|
// Now the count is at 0, assuming the other thread has not
|
||||
|
// started yet; otherwise it should be at 1.
|
||||
|
|
||||
|
semaphore.p (); |
||||
|
//cout << "1: done\n";
|
||||
|
}); |
||||
|
|
||||
|
Utils::sleep_millis(1000); |
||||
|
|
||||
|
thread thread2([&]() { |
||||
|
semaphore.v(); |
||||
|
}); |
||||
|
|
||||
|
thread1.join(); |
||||
|
thread2.join(); |
||||
|
|
||||
|
assert (semaphore.load() == 0); |
||||
|
}); |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
void many_threads() |
||||
|
{ |
||||
|
int i; |
||||
|
|
||||
|
#define N 1000 |
||||
|
thread threads[N]; |
||||
|
std::cout << "starting " << N |
||||
|
<< " threads, each starting and joining a thread pair...\n"; |
||||
|
for (i = 0; i < N; i ++) |
||||
|
threads [i] = make_two_threads_for_many_threads (); |
||||
|
std::cout << "joining threads...\n"; |
||||
|
for (i = 0; i < N; i ++) |
||||
|
threads [i].join(); |
||||
|
#undef N |
||||
|
std::cout << "many_threads done.\n\n"; |
||||
|
} |
||||
|
|
||||
|
void v_times (CountingSemaphore &semaphore, |
||||
|
int times) |
||||
|
{ |
||||
|
std::cout << "V'ing " << times << " times...\n"; |
||||
|
for (int i = 0; i < times; i ++) |
||||
|
semaphore.v (); |
||||
|
std::cout << "... I V'd " << times << " times.\n"; |
||||
|
} |
||||
|
|
||||
|
void p_times (CountingSemaphore &semaphore, |
||||
|
int times) |
||||
|
{ |
||||
|
std::cout << "P'ing " << times << " times...\n"; |
||||
|
for (int i = 0; i < times; i ++) |
||||
|
semaphore.p (); |
||||
|
std::cout << "... I P'd " << times << " times.\n"; |
||||
|
} |
||||
|
|
||||
|
void few_threads() |
||||
|
{ |
||||
|
#define HALF_N (1000 * 1000 * 10) |
||||
|
#define N (HALF_N * 2) |
||||
|
CountingSemaphore semaphore; |
||||
|
|
||||
|
thread thread_p1([&]() { |
||||
|
p_times (semaphore, HALF_N); |
||||
|
}); |
||||
|
thread thread_v([&]() { |
||||
|
v_times (semaphore, N); |
||||
|
}); |
||||
|
thread thread_p2([&]() { |
||||
|
p_times (semaphore, HALF_N); |
||||
|
}); |
||||
|
#undef HALF_N |
||||
|
#undef N |
||||
|
thread_v.join(); |
||||
|
thread_p1.join(); |
||||
|
thread_p2.join(); |
||||
|
|
||||
|
assert (semaphore.load() == 0); |
||||
|
|
||||
|
std::cout << "few_thrads done.\n\n"; |
||||
|
} |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
many_threads (); |
||||
|
few_threads (); |
||||
|
return 0; |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
// This file is under GNU General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
#include <iostream> |
||||
|
#include <cassert> |
||||
|
|
||||
|
#include <pEp/pEpLog.hh> |
||||
|
#include <pEp/std_utils.hh> |
||||
|
|
||||
|
int main(int argc, char* argv[]) |
||||
|
{ |
||||
|
pEp::Adapter::pEpLog::set_enabled(true); |
||||
|
std::string filename = "test_rw.bin"; |
||||
|
|
||||
|
std::vector<char> v_out{}; |
||||
|
for (int i = 0; i < 1000; i++) { |
||||
|
v_out.push_back(pEp::Utils::random_char(0, 255)); |
||||
|
} |
||||
|
|
||||
|
pEp::Utils::file_write_bin(filename, v_out); |
||||
|
|
||||
|
std::vector<char> v_in = pEp::Utils::file_read_bin(filename); |
||||
|
|
||||
|
assert(v_in == v_out); |
||||
|
} |
@ -0,0 +1,39 @@ |
|||||
|
#include <pEp/std_utils.hh> |
||||
|
#include <pEp/pEpLog.hh> |
||||
|
#include <iostream> |
||||
|
#include <cassert> |
||||
|
#include <pEp/pitytest11/PityTest.hh> |
||||
|
|
||||
|
using namespace pEp; |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
pEp::Adapter::pEpLog::set_enabled(true); |
||||
|
|
||||
|
{ |
||||
|
// Valid hex string
|
||||
|
std::string str_in{ "FFABCD00EF123200" }; |
||||
|
std::vector<unsigned char> bin = Utils::hex2bin<unsigned char>(str_in); |
||||
|
PITYASSERT(str_in.length() == bin.size() * 2, "Size error"); |
||||
|
|
||||
|
std::string str_out = pEp::Utils::bin2hex(bin); |
||||
|
pEpLog("Hex_IN : '" + Utils::to_lower(str_in) + "'"); |
||||
|
pEpLog("Hex_OUT : '" + Utils::to_lower(str_out) + "'"); |
||||
|
|
||||
|
PITYASSERT(Utils::to_lower(str_in) == Utils::to_lower(str_out), "roundtrip failed"); |
||||
|
} |
||||
|
|
||||
|
{ |
||||
|
// Uneven string throws
|
||||
|
std::string str_in{ "FFA" }; |
||||
|
PITYASSERT_THROWS(Utils::hex2bin<char>(str_in), "Uneven string should throw"); |
||||
|
} |
||||
|
|
||||
|
{ |
||||
|
// Non-hex chars
|
||||
|
std::string str_in{ "pEp!" }; |
||||
|
PITYASSERT_THROWS(Utils::hex2bin<char>(str_in), "Invalid hex chars should throw"); |
||||
|
} |
||||
|
|
||||
|
pEpLog("All tests passsed"); |
||||
|
} |
@ -0,0 +1,105 @@ |
|||||
|
// This file is under GNU General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#include "pc_container.hh" |
||||
|
#include <cstdio> |
||||
|
#include <cstdlib> |
||||
|
#include <iostream> |
||||
|
#include <thread> |
||||
|
|
||||
|
using namespace pEp; |
||||
|
|
||||
|
// Producer's data:
|
||||
|
class P { |
||||
|
public: |
||||
|
P(int i) : data{ new char[64] } |
||||
|
{ |
||||
|
snprintf(data, 63, "%i", i); |
||||
|
} |
||||
|
|
||||
|
P(const P&) = delete; |
||||
|
void operator=(const P&) = delete; |
||||
|
|
||||
|
~P() |
||||
|
{ |
||||
|
std::cerr << "~P(): data=" << (data ? data : "(NULL)") << '\n'; |
||||
|
delete[] data; |
||||
|
} |
||||
|
|
||||
|
char* data; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// Consumer's data:
|
||||
|
class C { |
||||
|
public: |
||||
|
C(int _i) : i(_i) {} |
||||
|
int i; |
||||
|
}; |
||||
|
|
||||
|
pc_container<P, C> pc; |
||||
|
|
||||
|
void consumer_thread() |
||||
|
{ |
||||
|
bool keep_running = true; |
||||
|
int sum = 0; |
||||
|
while (keep_running) { |
||||
|
for (auto& q : pc) { |
||||
|
switch (q.state()) { |
||||
|
case PC_State::Created: { |
||||
|
const int value = atoi(q.pdata->data); |
||||
|
if (value < 0) { |
||||
|
std::cerr << "Q\n"; |
||||
|
keep_running = false; |
||||
|
} else { |
||||
|
std::cerr << "C"; |
||||
|
q.cdata = new C(value); |
||||
|
sum += q.cdata->i; |
||||
|
} |
||||
|
break; |
||||
|
} |
||||
|
case PC_State::Deleted: { |
||||
|
std::cerr << "D"; |
||||
|
sum -= q.cdata->i; |
||||
|
delete q.cdata; |
||||
|
break; |
||||
|
} |
||||
|
case PC_State::Changed: { |
||||
|
std::cerr << "X"; |
||||
|
sum -= q.cdata->i; |
||||
|
delete q.cdata; |
||||
|
q.cdata = new C(atoi(q.pdata->data)); |
||||
|
sum += q.cdata->i; |
||||
|
break; |
||||
|
} |
||||
|
default: |
||||
|
throw "Illegal state"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
std::cout << "Consumer sum: " << sum << ".\n"; |
||||
|
} |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
for (int i = 0; i < 10; ++i) { |
||||
|
pc.insert(new P(i)); |
||||
|
} |
||||
|
|
||||
|
std::thread t{ &consumer_thread }; |
||||
|
|
||||
|
for (int i = 10; i < 100; ++i) { |
||||
|
pc.insert(new P(i)); |
||||
|
} |
||||
|
|
||||
|
while (!pc.empty()) { |
||||
|
auto q = pc.begin(); |
||||
|
delete q->pdata; |
||||
|
pc.erase(q); |
||||
|
} |
||||
|
|
||||
|
pc.insert(new P(-1)); |
||||
|
|
||||
|
t.join(); |
||||
|
} |
@ -0,0 +1,64 @@ |
|||||
|
#include <pEp/std_utils.hh> |
||||
|
#include <pEp/pEpLog.hh> |
||||
|
#include <pEp/pitytest11/PityTest.hh> |
||||
|
#include <iostream> |
||||
|
#include <chrono> |
||||
|
|
||||
|
using namespace pEp; |
||||
|
|
||||
|
|
||||
|
int test_random_string_fast() |
||||
|
{ |
||||
|
pEpLog("Test test_random_string_fast() correct length, min & max"); |
||||
|
for (int i = 0; i < 1000; i++) { |
||||
|
uint len = Utils::random_fast(5000); |
||||
|
std::string res = Utils::random_string_fast(0, 255, len); |
||||
|
PITYASSERT( |
||||
|
res.length() == len, |
||||
|
"random_string_fast: wrong length: " + |
||||
|
std::to_string(res.length()) + " is not " + std::to_string(len)); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
pEp::Adapter::pEpLog::set_enabled(true); |
||||
|
|
||||
|
test_random_string_fast(); |
||||
|
|
||||
|
pEpLog("Random functions benchmark"); |
||||
|
int nr_mb = 10; |
||||
|
int nr_bytes = 1024 * 1024 * nr_mb; |
||||
|
pEpLog("generating " + std::to_string(nr_mb) + "MB's of random"); |
||||
|
|
||||
|
{ |
||||
|
pEpLog("Utils::random_char()"); |
||||
|
auto time_start = std::chrono::steady_clock::now(); |
||||
|
for (int i = 0; i < nr_bytes; i++) { |
||||
|
Utils::random_char(0, 255); |
||||
|
} |
||||
|
auto time_end = std::chrono::steady_clock::now(); |
||||
|
double duration_ms = (double)std::chrono::duration_cast<std::chrono::microseconds>( |
||||
|
time_end - time_start) |
||||
|
.count() / |
||||
|
1000; |
||||
|
pEpLog("Time [ms/mbyte]:" + std::to_string(duration_ms / double(nr_mb))); |
||||
|
} |
||||
|
std::cout << "" << std::endl; |
||||
|
{ |
||||
|
pEpLog("Utils::Fastrand()"); |
||||
|
auto time_start = std::chrono::steady_clock::now(); |
||||
|
for (int i = 0; i < nr_bytes; i++) { |
||||
|
Utils::random_fast(255); |
||||
|
} |
||||
|
auto time_end = std::chrono::steady_clock::now(); |
||||
|
double duration_ms = (double)std::chrono::duration_cast<std::chrono::microseconds>( |
||||
|
time_end - time_start) |
||||
|
.count() / |
||||
|
1000; |
||||
|
|
||||
|
pEpLog("Time [ms/mbyte]:" + std::to_string(duration_ms / double(nr_mb))); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
// This file is under GNU General Public License 3.0
|
||||
|
// see LICENSE.txt
|
||||
|
|
||||
|
#include <iostream> |
||||
|
#include <thread> |
||||
|
#include <pEp/std_utils.hh> |
||||
|
#include "../src/Semaphore.hh" |
||||
|
|
||||
|
using namespace std; |
||||
|
using namespace pEp; |
||||
|
|
||||
|
int main() |
||||
|
{ |
||||
|
Semaphore semaphore; |
||||
|
|
||||
|
thread thread1([&]() { |
||||
|
cout << "1: before stop\n"; |
||||
|
semaphore.stop(); |
||||
|
cout << "1: now on stop\n"; |
||||
|
semaphore.try_wait(); |
||||
|
cout << "1: and on go again\n"; |
||||
|
semaphore.try_wait(); |
||||
|
cout << "1: keep going\n"; |
||||
|
}); |
||||
|
|
||||
|
Utils::sleep_millis(1000); |
||||
|
|
||||
|
thread thread2([&]() { |
||||
|
cout << "2: setting go\n"; |
||||
|
semaphore.go(); |
||||
|
}); |
||||
|
|
||||
|
thread1.join(); |
||||
|
thread2.join(); |
||||
|
|
||||
|
return 0; |
||||
|
} |
Loading…
Reference in new issue