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

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

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