Commit 6434f4d8 authored by Pavel Vainerman's avatar Pavel Vainerman

(IONotifyContoller): оптимизация функции localSetValue, попытка минимизировать,

вызовы и блокировки.
parent 16149668
...@@ -302,7 +302,7 @@ int main(int argc, char* argv[]) ...@@ -302,7 +302,7 @@ int main(int argc, char* argv[])
mypack.addAData(d); mypack.addAData(d);
} }
for( unsigned int i = 0; i < count; i++ ) for( size_t i = 0; i < count; i++ )
mypack.addDData(i, i); mypack.addDData(i, i);
Poco::Net::SocketAddress sa(s_host, port); Poco::Net::SocketAddress sa(s_host, port);
......
...@@ -145,7 +145,8 @@ class IOController: ...@@ -145,7 +145,8 @@ class IOController:
protected: protected:
// доступ к элементам через итератор // доступ к элементам через итератор
virtual void localSetValueIt( IOStateList::iterator& it, const UniSetTypes::ObjectId sid, // return итоговое значение
virtual long localSetValueIt( IOStateList::iterator& it, const UniSetTypes::ObjectId sid,
CORBA::Long value, UniSetTypes::ObjectId sup_id ); CORBA::Long value, UniSetTypes::ObjectId sup_id );
virtual long localGetValue( IOStateList::iterator& it, const UniSetTypes::ObjectId sid ); virtual long localGetValue( IOStateList::iterator& it, const UniSetTypes::ObjectId sid );
...@@ -158,7 +159,7 @@ class IOController: ...@@ -158,7 +159,7 @@ class IOController:
const UniSetTypes::ObjectId sid ); const UniSetTypes::ObjectId sid );
// -- работа через указатель --- // -- работа через указатель ---
virtual void localSetValue( std::shared_ptr<USensorInfo>& usi, CORBA::Long value, UniSetTypes::ObjectId sup_id ); virtual long localSetValue( std::shared_ptr<USensorInfo>& usi, CORBA::Long value, UniSetTypes::ObjectId sup_id );
long localGetValue( std::shared_ptr<USensorInfo>& usi) ; long localGetValue( std::shared_ptr<USensorInfo>& usi) ;
protected: protected:
...@@ -316,7 +317,6 @@ class IOController: ...@@ -316,7 +317,6 @@ class IOController:
inline UniSetTypes::SensorMessage makeSensorMessage() inline UniSetTypes::SensorMessage makeSensorMessage()
{ {
UniSetTypes::SensorMessage sm; UniSetTypes::SensorMessage sm;
UniSetTypes::uniset_rwmutex_rlock lock(val_lock);
sm.id = si.id; sm.id = si.id;
sm.node = si.node; // uniset_conf()->getLocalNode()? sm.node = si.node; // uniset_conf()->getLocalNode()?
sm.sensor_type = type; sm.sensor_type = type;
......
...@@ -276,7 +276,7 @@ class IONotifyController: ...@@ -276,7 +276,7 @@ class IONotifyController:
virtual void initItem(std::shared_ptr<USensorInfo>& usi, IOController* ic ); virtual void initItem(std::shared_ptr<USensorInfo>& usi, IOController* ic );
//! посылка информации об изменении состояния датчика //! посылка информации об изменении состояния датчика
virtual void send( ConsumerListInfo& lst, UniSetTypes::SensorMessage& sm ); virtual void send( ConsumerListInfo& lst, const UniSetTypes::SensorMessage& sm );
//! проверка срабатывания пороговых датчиков //! проверка срабатывания пороговых датчиков
virtual void checkThreshold( std::shared_ptr<USensorInfo>& usi, bool send = true ); virtual void checkThreshold( std::shared_ptr<USensorInfo>& usi, bool send = true );
...@@ -303,7 +303,7 @@ class IONotifyController: ...@@ -303,7 +303,7 @@ class IONotifyController:
void onChangeUndefinedState( std::shared_ptr<USensorInfo>& usi, IOController* ic ); void onChangeUndefinedState( std::shared_ptr<USensorInfo>& usi, IOController* ic );
// функция для работы напрямую с указателем (оптимизация) // функция для работы напрямую с указателем (оптимизация)
virtual void localSetValue( std::shared_ptr<USensorInfo>& usi, virtual long localSetValue( std::shared_ptr<USensorInfo>& usi,
CORBA::Long value, UniSetTypes::ObjectId sup_id ) override; CORBA::Long value, UniSetTypes::ObjectId sup_id ) override;
//! \warning Оптимизация использует userdata! Это опасно, если кто-то ещё захочет его использовать! //! \warning Оптимизация использует userdata! Это опасно, если кто-то ещё захочет его использовать!
......
...@@ -254,7 +254,7 @@ void IOController::setValue( UniSetTypes::ObjectId sid, CORBA::Long value, UniSe ...@@ -254,7 +254,7 @@ void IOController::setValue( UniSetTypes::ObjectId sid, CORBA::Long value, UniSe
localSetValueIt( li, sid, value, sup_id ); localSetValueIt( li, sid, value, sup_id );
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void IOController::localSetValueIt( IOController::IOStateList::iterator& li, long IOController::localSetValueIt( IOController::IOStateList::iterator& li,
UniSetTypes::ObjectId sid, UniSetTypes::ObjectId sid,
CORBA::Long value, UniSetTypes::ObjectId sup_id ) CORBA::Long value, UniSetTypes::ObjectId sup_id )
{ {
...@@ -273,13 +273,17 @@ void IOController::localSetValueIt( IOController::IOStateList::iterator& li, ...@@ -273,13 +273,17 @@ void IOController::localSetValueIt( IOController::IOStateList::iterator& li,
throw IOController_i::NameNotFound(err.str().c_str()); throw IOController_i::NameNotFound(err.str().c_str());
} }
localSetValue(li->second, value, sup_id); return localSetValue(li->second, value, sup_id);
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi, long IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
CORBA::Long value, UniSetTypes::ObjectId sup_id ) CORBA::Long value, UniSetTypes::ObjectId sup_id )
{ {
// if( !usi ) - не проверяем, т.к. считаем что это внутренние функции и несуществующий указатель передать не могут
bool changed = false; bool changed = false;
bool blockChanged = false;
long retValue = value;
{ {
// lock // lock
...@@ -291,7 +295,7 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi, ...@@ -291,7 +295,7 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
changed = ( usi->real_value != value ); changed = ( usi->real_value != value );
// если поменялось состояние блокировки // если поменялось состояние блокировки
bool blockChanged = ( blocked != (usi->value == usi->d_off_value ) ); blockChanged = ( blocked != (usi->value == usi->d_off_value ) );
if( changed || blockChanged ) if( changed || blockChanged )
{ {
...@@ -305,6 +309,7 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi, ...@@ -305,6 +309,7 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
usi->real_value = value; usi->real_value = value;
usi->value = (blocked ? usi->d_off_value : value); usi->value = (blocked ? usi->d_off_value : value);
retValue = usi->value;
// запоминаем время изменения // запоминаем время изменения
struct timespec tm = UniSetTypes::now_to_timespec(); struct timespec tm = UniSetTypes::now_to_timespec();
...@@ -315,7 +320,7 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi, ...@@ -315,7 +320,7 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
try try
{ {
if( changed ) if( changed || blockChanged )
{ {
uniset_rwmutex_wrlock l(usi->changeMutex); uniset_rwmutex_wrlock l(usi->changeMutex);
usi->sigChange.emit(usi, this); usi->sigChange.emit(usi, this);
...@@ -325,13 +330,15 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi, ...@@ -325,13 +330,15 @@ void IOController::localSetValue( std::shared_ptr<USensorInfo>& usi,
try try
{ {
if( changed ) if( changed || blockChanged )
{ {
std::lock_guard<std::mutex> l(siganyMutex); std::lock_guard<std::mutex> l(siganyMutex);
sigAnyChange.emit(usi, this); sigAnyChange.emit(usi, this);
} }
} }
catch(...) {} catch(...) {}
return retValue;
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
IOType IOController::getIOType( UniSetTypes::ObjectId sid ) IOType IOController::getIOType( UniSetTypes::ObjectId sid )
......
...@@ -364,69 +364,43 @@ void IONotifyController::ask( AskMap& askLst, const UniSetTypes::ObjectId sid, ...@@ -364,69 +364,43 @@ void IONotifyController::ask( AskMap& askLst, const UniSetTypes::ObjectId sid,
} }
} }
// ------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------
void IONotifyController::localSetValue( std::shared_ptr<IOController::USensorInfo>& usi, long IONotifyController::localSetValue( std::shared_ptr<IOController::USensorInfo>& usi,
CORBA::Long value, UniSetTypes::ObjectId sup_id ) CORBA::Long value, UniSetTypes::ObjectId sup_id )
{ {
CORBA::Long prevValue = 0; // if( !usi ) - не проверяем, т.к. считаем что это внутренние функции и несуществующий указатель передать не могут
try CORBA::Long prevValue = value;
{
// Если датчик не найден здесь сработает исключение
prevValue = IOController::localGetValue( usi );
}
catch( IOController_i::Undefined )
{ {
// чтобы сработало prevValue != usi->value
// искусственно меняем значение
uniset_rwmutex_rlock lock(usi->val_lock); uniset_rwmutex_rlock lock(usi->val_lock);
prevValue = usi->value + 1; prevValue = usi->value;
} }
IOController::localSetValue(usi, value, sup_id); CORBA::Long realValue = IOController::localSetValue(usi, value, sup_id);
// Копируем "под замком" только значимые части зависящие от value // Рассылаем уведомления только в случае изменения значения
// т.к. всё остальное не меняется в процессе работы программы и по сути readonly
CORBA::Long realValue = prevValue;
CORBA::ULong tv_sec = 0;
CORBA::ULong tv_nsec = 0;
CORBA::Boolean undefined = false;
IOController_i::CalibrateInfo ci;
// lock
{
uniset_rwmutex_rlock lock(usi->val_lock);
realValue = usi->value;
tv_sec = usi->tv_sec;
tv_nsec = usi->tv_nsec;
undefined = usi->undefined;
ci = usi->ci;
} // unlock value
// Рассылаем уведомления только в слуае изменения значения
// -------- // --------
// сравниваем именно с realValue
// т.к. фактическое сохранённое значение может быть изменено
// фильтрами или блокировками..
if( prevValue == realValue ) if( prevValue == realValue )
return; return realValue;
SensorMessage sm(1); // <-- вызываем dummy конструктор т.к. потом все поля всё-равно сами инициализируем SensorMessage sm(1); // <-- вызываем dummy конструктор т.к. потом все поля всё-равно сами инициализируем
{
// lock
// uniset_rwmutex_rlock lock(usi->val_lock);
sm.id = usi->si.id; sm.id = usi->si.id;
sm.node = uniset_conf()->getLocalNode(); sm.node = usi->si.node; // uniset_conf()->getLocalNode();
sm.value = realValue; sm.value = realValue;
sm.undefined = undefined;
sm.priority = (Message::Priority)usi->priority; sm.priority = (Message::Priority)usi->priority;
sm.supplier = sup_id; // owner_id sm.supplier = sup_id; // owner_id
sm.sensor_type = usi->type; sm.sensor_type = usi->type;
sm.sm_tv.tv_sec = tv_sec;
sm.sm_tv.tv_nsec = tv_nsec; // копируем под lock только изменяемую часть
sm.tm = { (long)tv_sec, (long)tv_nsec }; // lock
sm.ci = ci; {
} // unlock uniset_rwmutex_rlock lock(usi->val_lock);
sm.undefined = usi->undefined;
sm.sm_tv.tv_sec = usi->tv_sec;
sm.sm_tv.tv_nsec = usi->tv_nsec;
sm.ci = usi->ci;
} // unlock value
sm.tm = sm.sm_tv;
try try
{ {
...@@ -452,6 +426,8 @@ void IONotifyController::localSetValue( std::shared_ptr<IOController::USensorInf ...@@ -452,6 +426,8 @@ void IONotifyController::localSetValue( std::shared_ptr<IOController::USensorInf
checkThreshold(usi, true); checkThreshold(usi, true);
} }
catch(...) {} catch(...) {}
return realValue;
} }
// ----------------------------------------------------------------------------------------- // -----------------------------------------------------------------------------------------
/*! /*!
...@@ -459,7 +435,7 @@ void IONotifyController::localSetValue( std::shared_ptr<IOController::USensorInf ...@@ -459,7 +435,7 @@ void IONotifyController::localSetValue( std::shared_ptr<IOController::USensorInf
Возможно нужно ввести своего агента на удалённой стороне, который будет заниматься Возможно нужно ввести своего агента на удалённой стороне, который будет заниматься
только приёмом сообщений и локальной рассылкой. Lav только приёмом сообщений и локальной рассылкой. Lav
*/ */
void IONotifyController::send( ConsumerListInfo& lst, UniSetTypes::SensorMessage& sm ) void IONotifyController::send( ConsumerListInfo& lst, const UniSetTypes::SensorMessage& sm )
{ {
TransportMessage tmsg(sm.transport_msg()); TransportMessage tmsg(sm.transport_msg());
......
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