// Copyright (C) 2007 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_THREADED_OBJECT_EXTENSIOn_CPP
#define DLIB_THREADED_OBJECT_EXTENSIOn_CPP
#include "threaded_object_extension.h"
#include "create_new_thread_extension.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
threaded_object::
threaded_object (
):
s(m_),
id1(0),
is_running_(false),
is_alive_(false),
should_stop_(false),
id_valid(false)
{
}
// ----------------------------------------------------------------------------------------
threaded_object::
~threaded_object (
)
{
try
{
DLIB_ASSERT(is_alive() == false,
"\tthreaded_object::~threaded_object()"
<< "\n\tYou have let a threaded object destruct itself before terminating its thread"
<< "\n\tthis: " << this
);
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
assert(false);
abort();
}
}
// ----------------------------------------------------------------------------------------
bool threaded_object::
is_running (
) const
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tbool threaded_object::is_running()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
return is_running_;
}
// ----------------------------------------------------------------------------------------
bool threaded_object::
is_alive (
) const
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tbool threaded_object::is_alive()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
return is_alive_;
}
// ----------------------------------------------------------------------------------------
void threaded_object::
wait (
) const
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tvoid threaded_object::wait()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
while (is_alive_)
s.wait();
}
// ----------------------------------------------------------------------------------------
void threaded_object::
start (
)
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tvoid threaded_object::start()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
if (is_alive_ == false)
{
if (create_new_thread<threaded_object,&threaded_object::thread_helper>(*this) == false)
{
is_running_ = false;
throw thread_error();
}
}
is_alive_ = true;
is_running_ = true;
should_stop_ = false;
s.broadcast();
}
// ----------------------------------------------------------------------------------------
void threaded_object::
restart (
)
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tvoid threaded_object::restart()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
if (is_alive_ == false)
{
if (create_new_thread<threaded_object,&threaded_object::thread_helper>(*this) == false)
{
is_running_ = false;
throw thread_error();
}
should_respawn_ = false;
}
else
{
should_respawn_ = true;
}
is_alive_ = true;
is_running_ = true;
should_stop_ = false;
s.broadcast();
}
// ----------------------------------------------------------------------------------------
void threaded_object::
set_respawn (
)
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tvoid threaded_object::set_respawn()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
should_respawn_ = true;
}
// ----------------------------------------------------------------------------------------
bool threaded_object::
should_respawn (
) const
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tbool threaded_object::should_respawn()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
return should_respawn_;
}
// ----------------------------------------------------------------------------------------
void threaded_object::
pause (
)
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tvoid threaded_object::pause()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
is_running_ = false;
}
// ----------------------------------------------------------------------------------------
void threaded_object::
stop (
)
{
auto_mutex M(m_);
DLIB_ASSERT(id1 != get_thread_id() || id_valid == false,
"\tvoid threaded_object::stop()"
<< "\n\tYou can NOT call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
should_stop_ = true;
is_running_ = false;
should_respawn_ = false;
s.broadcast();
}
// ----------------------------------------------------------------------------------------
bool threaded_object::
should_stop (
) const
{
auto_mutex M(m_);
DLIB_ASSERT(is_alive_ && id1 == get_thread_id() && id_valid == true,
"\tbool threaded_object::should_stop()"
<< "\n\tYou can only call this function from the thread that executes threaded_object::thread"
<< "\n\tthis: " << this
);
while (is_running_ == false && should_stop_ == false)
s.wait();
return should_stop_;
}
// ----------------------------------------------------------------------------------------
void threaded_object::
thread_helper(
)
{
#ifdef ENABLE_ASSERTS
id1 = get_thread_id();
id_valid = true;
#endif
while (true)
{
m_.lock();
should_respawn_ = false;
m_.unlock();
thread();
auto_mutex M(m_);
if (should_respawn_)
continue;
#ifdef ENABLE_ASSERTS
id_valid = false;
#endif
is_alive_ = false;
is_running_ = false;
should_stop_ = false;
s.broadcast();
return;
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_THREADED_OBJECT_EXTENSIOn_CPP