Commit 8eade6a3 authored by Pavel Vainerman's avatar Pavel Vainerman

(CommonEventLoop): переписал немного процесс активации

(попытка решить проблемму с "зависанием")
parent 35db506e
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
Name: libuniset2 Name: libuniset2
Version: 2.6 Version: 2.6
Release: alt2 Release: alt3
Summary: UniSet - library for building distributed industrial control systems Summary: UniSet - library for building distributed industrial control systems
License: LGPL License: LGPL
...@@ -508,6 +508,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname ...@@ -508,6 +508,9 @@ mv -f %buildroot%python_sitelibdir_noarch/* %buildroot%python_sitelibdir/%oname
# history of current unpublished changes # history of current unpublished changes
%changelog %changelog
* Tue Nov 22 2016 Pavel Vainerman <pv@altlinux.ru> 2.6-alt3
- CommonEventLoop: refactoring prepare process
* Mon Nov 21 2016 Pavel Vainerman <pv@altlinux.ru> 2.6-alt2 * Mon Nov 21 2016 Pavel Vainerman <pv@altlinux.ru> 2.6-alt2
- UNet: fixed bug in change receive channel - UNet: fixed bug in change receive channel
......
...@@ -58,8 +58,14 @@ class CommonEventLoop ...@@ -58,8 +58,14 @@ class CommonEventLoop
bool evIsActive() const noexcept; bool evIsActive() const noexcept;
/*! \return TRUE - если всё удалось. return актуален только для случая когда thread = true */ /*! \return TRUE - если всё удалось. return актуален только для случая когда thread = true
bool evrun( EvWatcher* w, bool thread = true ); * \param thread - создать отдельный (асинхронный) поток для event loop.
* Если thread=false - функция не вернёт управление и будет ждать завершения работы ( см. evstop())
* \param waitPrepareTimeout_msec - сколько ждать активации, либо функция вернёт false.
* Даже если thread = false, но wather не сможет быть "активирован" функция вернёт управление
* с return false.
*/
bool evrun( EvWatcher* w, bool thread = true, size_t waitPrepareTimeout_msec = 5000);
/*! \return TRUE - если это был последний EvWatcher и loop остановлен */ /*! \return TRUE - если это был последний EvWatcher и loop остановлен */
bool evstop( EvWatcher* w ); bool evstop( EvWatcher* w );
...@@ -83,6 +89,7 @@ class CommonEventLoop ...@@ -83,6 +89,7 @@ class CommonEventLoop
ev::dynamic_loop loop; ev::dynamic_loop loop;
ev::async evterm; ev::async evterm;
std::shared_ptr<std::thread> thr; std::shared_ptr<std::thread> thr;
std::mutex thr_mutex;
std::mutex term_mutex; std::mutex term_mutex;
std::condition_variable term_event; std::condition_variable term_event;
......
...@@ -31,7 +31,7 @@ CommonEventLoop::~CommonEventLoop() ...@@ -31,7 +31,7 @@ CommonEventLoop::~CommonEventLoop()
} }
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
bool CommonEventLoop::evrun(EvWatcher* w, bool thread ) bool CommonEventLoop::evrun( EvWatcher* w, bool thread, size_t waitTimeout_msec )
{ {
if( !w ) if( !w )
return false; return false;
...@@ -39,7 +39,7 @@ bool CommonEventLoop::evrun(EvWatcher* w, bool thread ) ...@@ -39,7 +39,7 @@ bool CommonEventLoop::evrun(EvWatcher* w, bool thread )
bool ret = false; bool ret = false;
{ {
{ {
std::unique_lock<std::mutex> l(wlist_mutex); std::lock_guard<std::mutex> lck(wlist_mutex);
for( auto& e: wlist ) for( auto& e: wlist )
{ {
if( e == w ) if( e == w )
...@@ -51,25 +51,43 @@ bool CommonEventLoop::evrun(EvWatcher* w, bool thread ) ...@@ -51,25 +51,43 @@ bool CommonEventLoop::evrun(EvWatcher* w, bool thread )
wlist.push_back(w); wlist.push_back(w);
} }
if( !thr )
{ {
thr = make_shared<std::thread>( [ = ] { CommonEventLoop::defaultLoop(); } ); std::lock_guard<std::mutex> lck(thr_mutex);
std::this_thread::sleep_for(std::chrono::milliseconds(30)); if( !thr )
{
thr = make_shared<std::thread>( [ = ] { CommonEventLoop::defaultLoop(); } );
std::unique_lock<std::mutex> locker(prep_mutex);
// ожидаем запуска loop
// иначе evprep.send() улетит в никуда
prep_event.wait_for(locker,std::chrono::milliseconds(waitTimeout_msec), [=]()
{
return (isrunning == false);
} );
if( !isrunning )
{
cerr << "(CommonEventLoop::evrun): " << w->wname() << " evloop NOT RUN!.." << endl;
return false;
}
}
} }
// готовим "указатель" на объект требующий активации
std::unique_lock<std::mutex> locker(prep_mutex); std::unique_lock<std::mutex> locker(prep_mutex);
wprep = w; wprep = w;
// взводим флаг
prep_notify = false; prep_notify = false;
// посылаем сигнал для обработки
evprep.send(); // будим default loop evprep.send(); // будим default loop
// ожидаем обработки evprepare (которая будет в defaultLoop) // ожидаем обработки evprepare (которая будет в defaultLoop)
while( !prep_notify ) prep_event.wait_for(locker,std::chrono::milliseconds(waitTimeout_msec), [=]()
{ {
prep_event.wait_for(locker,std::chrono::milliseconds(5000), [=]() return (prep_notify == true);
{ } );
return (prep_notify == true);
} );
}
// сбрасываем флаг // сбрасываем флаг
prep_notify = false; prep_notify = false;
...@@ -105,7 +123,7 @@ bool CommonEventLoop::evstop( EvWatcher* w ) ...@@ -105,7 +123,7 @@ bool CommonEventLoop::evstop( EvWatcher* w )
if( !w ) if( !w )
return false; return false;
std::unique_lock<std::mutex> l(wlist_mutex); std::lock_guard<std::mutex> l(wlist_mutex);
try try
{ {
...@@ -143,7 +161,7 @@ void CommonEventLoop::onPrepare() noexcept ...@@ -143,7 +161,7 @@ void CommonEventLoop::onPrepare() noexcept
{ {
prep_notify = false; prep_notify = false;
{ {
std::unique_lock<std::mutex> lock(prep_mutex); std::lock_guard<std::mutex> lock(prep_mutex);
if( wprep ) if( wprep )
{ {
try try
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment