159 lines
4.5 KiB
C++
159 lines
4.5 KiB
C++
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <cstdlib>
|
|
#include <ctime>
|
|
#include <dlib/misc_api.h>
|
|
#include <dlib/threads.h>
|
|
|
|
#include "tester.h"
|
|
|
|
namespace
|
|
{
|
|
using namespace test;
|
|
using namespace dlib;
|
|
using namespace std;
|
|
|
|
logger dlog("test.threads");
|
|
|
|
void test_async()
|
|
{
|
|
#if __cplusplus >= 201103
|
|
print_spinner();
|
|
auto v1 = dlib::async([]() { dlib::sleep(500); return 1; }).share();
|
|
auto v2 = dlib::async([v1]() { dlib::sleep(400); return v1.get()+1; }).share();
|
|
auto v3 = dlib::async([v2](int a) { dlib::sleep(300); return v2.get()+a; },2).share();
|
|
auto v4 = dlib::async([v3]() { dlib::sleep(200); return v3.get()+1; });
|
|
|
|
DLIB_TEST(v4.get() == 5);
|
|
|
|
print_spinner();
|
|
auto except = dlib::async([](){ dlib::sleep(300); throw error("oops"); });
|
|
bool got_exception = false;
|
|
try
|
|
{
|
|
except.get();
|
|
}
|
|
catch (error&e)
|
|
{
|
|
got_exception = true;
|
|
DLIB_TEST(e.what() == string("oops"));
|
|
}
|
|
DLIB_TEST(got_exception);
|
|
#endif
|
|
}
|
|
|
|
class threads_tester : public tester
|
|
{
|
|
public:
|
|
threads_tester (
|
|
) :
|
|
tester ("test_threads",
|
|
"Runs tests on the threads component."),
|
|
sm(cm)
|
|
{}
|
|
|
|
thread_specific_data<int> tsd;
|
|
rmutex cm;
|
|
rsignaler sm;
|
|
int count;
|
|
bool failure;
|
|
|
|
void perform_test (
|
|
)
|
|
{
|
|
failure = false;
|
|
print_spinner();
|
|
|
|
|
|
count = 10;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread1>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread2>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread3>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread4>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread5>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread6>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread7>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread8>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread9>(*this)) failure = true;
|
|
if (!create_new_thread<threads_tester,&threads_tester::thread10>(*this)) failure = true;
|
|
|
|
thread(66);
|
|
|
|
// this should happen in the main program thread
|
|
if (is_dlib_thread())
|
|
failure = true;
|
|
|
|
auto_mutex M(cm);
|
|
while (count > 0 && !failure)
|
|
sm.wait();
|
|
|
|
|
|
DLIB_TEST(!failure);
|
|
|
|
test_async();
|
|
}
|
|
|
|
void thread_end_handler (
|
|
)
|
|
{
|
|
auto_mutex M(cm);
|
|
--count;
|
|
if (count == 0)
|
|
sm.signal();
|
|
}
|
|
|
|
void thread1() { thread(1); }
|
|
void thread2()
|
|
{
|
|
thread(2);
|
|
if (is_dlib_thread() == false)
|
|
failure = true;
|
|
}
|
|
void thread3() { thread(3); }
|
|
void thread4() { thread(4); }
|
|
void thread5() { thread(5); }
|
|
void thread6() { thread(6); }
|
|
void thread7() { thread(7); }
|
|
void thread8() { thread(8); }
|
|
void thread9() { thread(9); }
|
|
void thread10() { thread(10); }
|
|
|
|
void thread (
|
|
int num
|
|
)
|
|
{
|
|
dlog << LTRACE << "starting thread num " << num;
|
|
if (is_dlib_thread())
|
|
register_thread_end_handler(*this,&threads_tester::thread_end_handler);
|
|
tsd.data() = num;
|
|
for (int i = 0; i < 0x3FFFF; ++i)
|
|
{
|
|
if ((i&0xFFF) == 0)
|
|
{
|
|
print_spinner();
|
|
dlib::sleep(10);
|
|
}
|
|
// if this isn't equal to num then there is a problem with the thread specific data stuff
|
|
if (tsd.data() != num)
|
|
{
|
|
auto_mutex M(cm);
|
|
failure = true;
|
|
sm.signal();
|
|
}
|
|
}
|
|
dlog << LTRACE << "ending of thread num " << num;
|
|
|
|
|
|
}
|
|
} a;
|
|
|
|
|
|
}
|
|
|
|
|
|
|