35 #include <QCoreApplication> 40 QAtomicInt ArnLink::_idCount(1);
59 ArnLink::ArnLink( ArnLink *parent,
const QString& name,
Arn::LinkFlags flags)
63 QString name_ = Arn::convertBaseName( name,
Arn::NameF());
67 _isFolder = flags.is( flags.
Folder);
68 _isProvider = name_.endsWith(
'!');
71 _subscribeTab = arnNullptr;
73 _children = _isFolder ?
new ArnLinkList : &nullArnLinkList;
77 _hasBeenSetup =
false;
79 _id = quint32( _idCount.fetchAndAddRelaxed(1));
83 _retireType = RetireType::None;
98 _twin->_twin = arnNullptr;
103 setParent( arnNullptr);
107 void ArnLink::resetHave()
112 _haveByteArray =
false;
113 _haveVariant =
false;
117 void ArnLink::needInt(
bool* isOk)
123 _val->valueInt = int( _val->valueReal);
126 _val->valueInt = _val->valueString.toInt( &isOk2);
129 _val->valueInt = _val->valueByteArray.toInt( &isOk2);
132 _val->valueInt = _val->valueVariant.toInt( &isOk2);
145 void ArnLink::needReal(
bool* isOk)
151 _val->valueReal = (
ARNREAL)_val->valueInt;
153 #
if defined( ARNREAL_FLOAT)
155 _val->valueReal = _val->valueString.toFloat( &isOk2);
158 _val->valueReal = _val->valueByteArray.toFloat( &isOk2);
161 _val->valueReal = _val->valueVariant.toFloat( &isOk2);
165 _val->valueReal = _val->valueString.toDouble( &isOk2);
168 _val->valueReal = _val->valueByteArray.toDouble( &isOk2);
171 _val->valueReal = _val->valueVariant.toDouble( &isOk2);
175 _val->valueReal = 0.0;
185 QString ArnLink::objectName()
const 191 ArnLink* ArnLink::parent()
const 197 void ArnLink::setParent( ArnLink* parent)
200 _parent->_children->removeOne(
this);
205 _parent->_children->append(
this);
216 void ArnLink::doValueChanged(
int sendId,
const QByteArray* valueData,
217 const ArnLinkHandle& handleData)
228 int len = recipients.size();
229 for (
int i = 0; i < len; ++i) {
231 ev->setAccepted(
true);
232 coreItem->sendArnEventItem( ev,
false);
238 void ArnLink::sendArnEvent(
ArnEvent* ev)
250 QThread* curThread = QThread::currentThread();
252 if (_subscribeTab && !_subscribeTab->isEmpty()) {
254 if (coreItem->
thread() == curThread) {
255 subscrInThread += coreItem;
260 coreItem->sendArnEventItem( evClone,
true,
true);
267 sendEventsInThread( ev, subscrInThread);
271 void ArnLink::sendEventsDirRoot(
ArnEvent* ev, ArnLink* startLink)
273 ArnLink* link = startLink;
276 link->sendArnEvent( ev);
277 link = link->parent();
282 void ArnLink::sendEventArnM(
ArnEvent* ev)
284 bool isMainThread =
true;
285 QObject* objArnM = arnM();
288 if (QThread::currentThread() != objArnM->thread()) {
289 isMainThread =
false;
291 QCoreApplication::postEvent( objArnM, evClone);
296 QCoreApplication::sendEvent( objArnM, ev);
301 void ArnLink::setValue(
int value,
int sendId,
bool useUncrossed)
304 if (_twin && !useUncrossed) {
305 _twin->setValue( value, sendId,
true);
309 if (_mutex) _mutex->lock();
311 _val->valueInt = value;
314 ++_val->localUpdateCount;
315 if (_mutex) _mutex->unlock();
317 if (_mutex && _isPipeMode) {
319 QByteArray::number( value);
320 doValueChanged( sendId, &valueData);
323 doValueChanged( sendId);
328 void ArnLink::setValue(
ARNREAL value,
int sendId,
bool useUncrossed)
331 if (_twin && !useUncrossed) {
332 _twin->setValue( value, sendId,
true);
336 if (_mutex) _mutex->lock();
338 _val->valueReal = value;
341 ++_val->localUpdateCount;
342 if (_mutex) _mutex->unlock();
344 if (_mutex && _isPipeMode) {
345 #if defined( ARNREAL_FLOAT) 347 QByteArray::number( value,
'g', std::numeric_limits<float>::digits10);
350 QByteArray::number( value,
'g', std::numeric_limits<double>::digits10);
352 doValueChanged( sendId, &valueData);
355 doValueChanged( sendId);
360 void ArnLink::setValue(
const QString& value,
int sendId,
bool useUncrossed,
361 const ArnLinkHandle& handleData)
364 if (_twin && !useUncrossed) {
365 _twin->setValue( value, sendId,
true, handleData);
369 if (_mutex) _mutex->lock();
371 _val->valueString.resize(0);
372 _val->valueString += value;
375 if (!handleData.flags().is( ArnLinkHandle::Flags::FromRemote))
376 ++_val->localUpdateCount;
377 if (_mutex) _mutex->unlock();
379 if (_mutex && (_isPipeMode || !handleData.isNull())) {
382 doValueChanged( sendId, &valueData, handleData);
385 doValueChanged( sendId, arnNullptr, handleData);
390 void ArnLink::setValue(
const QByteArray& value,
int sendId,
bool useUncrossed,
391 const ArnLinkHandle& handleData)
394 if (_twin && !useUncrossed) {
395 _twin->setValue( value, sendId,
true, handleData);
399 if (_mutex) _mutex->lock();
401 _val->valueByteArray.resize(0);
402 _val->valueByteArray += value;
404 _haveByteArray =
true;
405 if (!handleData.flags().is( ArnLinkHandle::Flags::FromRemote))
406 ++_val->localUpdateCount;
407 if (_mutex) _mutex->unlock();
409 if (_mutex && (_isPipeMode || !handleData.isNull())) {
411 doValueChanged( sendId, &valueData, handleData);
414 doValueChanged( sendId, arnNullptr, handleData);
419 void ArnLink::setValue(
const QVariant& value,
int sendId,
bool useUncrossed,
420 const ArnLinkHandle& handleData)
423 if (_twin && !useUncrossed) {
424 _twin->setValue( value, sendId,
true, handleData);
428 if (_mutex) _mutex->lock();
430 _val->valueVariant = value;
433 if (!handleData.flags().is( ArnLinkHandle::Flags::FromRemote))
434 ++_val->localUpdateCount;
435 if (_mutex) _mutex->unlock();
437 if (_mutex && _isPipeMode) {
440 value.toString().toUtf8();
441 doValueChanged( sendId, &valueData, handleData);
444 doValueChanged( sendId, arnNullptr, handleData);
449 void ArnLink::setIgnoredValue(
const ArnLinkHandle& handleData)
453 if (_mutex) _mutex->lock();
454 if (!handleData.flags().is( ArnLinkHandle::Flags::FromRemote))
455 ++_val->localUpdateCount;
456 if (_mutex) _mutex->unlock();
460 void ArnLink::setBits(
int mask,
int value,
int sendId,
bool useUncrossed)
465 if (_isAtomicOpProvider && !_twin->_isAtomicOpProvider) {
466 return _twin->setBits( mask, value, sendId, useUncrossed);
468 if (!_twin->_isAtomicOpProvider) {
472 _twin->sendArnEvent( &ev);
478 if (_mutex) _mutex->lock();
482 int newValue = (_val->valueInt & ~mask) | (value & mask);
483 _val->valueInt = newValue;
486 ++_val->localUpdateCount;
488 if (_mutex) _mutex->unlock();
490 if (_twin && !useUncrossed) {
491 _twin->setValue( newValue, sendId,
true);
494 if (_mutex && _isPipeMode) {
496 QByteArray::number( newValue);
497 doValueChanged( sendId, &valueData);
500 doValueChanged( sendId);
505 void ArnLink::addValue(
int value,
int sendId,
bool useUncrossed)
510 if (_isAtomicOpProvider && !_twin->_isAtomicOpProvider) {
511 return _twin->addValue( value, sendId, useUncrossed);
513 if (!_twin->_isAtomicOpProvider) {
517 _twin->sendArnEvent( &ev);
523 if (_mutex) _mutex->lock();
527 int newValue = _val->valueInt + value;
528 _val->valueInt = newValue;
531 ++_val->localUpdateCount;
533 if (_mutex) _mutex->unlock();
535 if (_twin && !useUncrossed) {
536 _twin->setValue( newValue, sendId,
true);
539 if (_mutex && _isPipeMode) {
541 QByteArray::number( newValue);
542 doValueChanged( sendId, &valueData);
545 doValueChanged( sendId);
550 void ArnLink::addValue(
ARNREAL value,
int sendId,
bool useUncrossed)
555 if (_isAtomicOpProvider && !_twin->_isAtomicOpProvider) {
556 return _twin->addValue( value, sendId, useUncrossed);
558 if (!_twin->_isAtomicOpProvider) {
562 _twin->sendArnEvent( &ev);
568 if (_mutex) _mutex->lock();
572 ARNREAL newValue = _val->valueReal + value;
573 _val->valueReal = newValue;
576 ++_val->localUpdateCount;
578 if (_mutex) _mutex->unlock();
580 if (_twin && !useUncrossed) {
581 _twin->setValue( newValue, sendId,
true);
584 if (_mutex && _isPipeMode) {
586 QByteArray::number( newValue);
587 doValueChanged( sendId, &valueData);
590 doValueChanged( sendId);
595 int ArnLink::toInt(
bool* isOk)
600 if (_mutex) _mutex->lock();
605 int retVal = _val->valueInt;
609 return _val->valueInt;
613 ARNREAL ArnLink::toReal(
bool* isOk)
617 if (!_val)
return 0.0;
618 if (_mutex) _mutex->lock();
623 ARNREAL retVal = _val->valueReal;
627 return _val->valueReal;
631 QString ArnLink::toString(
bool* isOk)
635 if (!_val)
return QString();
636 if (_mutex) _mutex->lock();
640 _val->valueString.resize(0);
643 _val->valueString += QString::number(_val->valueInt, 10);
646 #if defined( ARNREAL_FLOAT) 647 _val->valueString += QString::number(_val->valueReal,
'g', std::numeric_limits<float>::digits10);
649 _val->valueString += QString::number(_val->valueReal,
'g', std::numeric_limits<double>::digits10);
653 _val->valueString += QString::fromUtf8( _val->valueByteArray.constData(), _val->valueByteArray.size());
656 isOk2 = _val->valueVariant.canConvert( QVariant::String);
657 _val->valueString += _val->valueVariant.toString();
668 QString retVal = _val->valueString;
672 return _val->valueString;
676 QByteArray ArnLink::toByteArray(
bool* isOk)
680 if (!_val)
return QByteArray();
681 if (_mutex) _mutex->lock();
683 if (!_haveByteArray) {
685 _val->valueByteArray.resize(0);
688 _val->valueByteArray += QByteArray::number( _val->valueInt, 10);
691 #if defined( ARNREAL_FLOAT) 692 _val->valueByteArray += QByteArray::number( _val->valueReal,
'g', std::numeric_limits<float>::digits10);
694 _val->valueByteArray += QByteArray::number( _val->valueReal,
'g', std::numeric_limits<double>::digits10);
698 _val->valueByteArray += _val->valueString.toUtf8();
701 isOk2 = _val->valueVariant.canConvert( QVariant::String);
702 _val->valueByteArray += _val->valueVariant.toString().toUtf8();
707 _haveByteArray = isOk2;
713 QByteArray retVal = _val->valueByteArray;
717 return _val->valueByteArray;
721 QVariant ArnLink::toVariant(
bool* isOk)
725 if (!_val)
return QVariant();
726 if (_mutex) _mutex->lock();
732 _val->valueVariant = _val->valueInt;
735 _val->valueVariant = _val->valueReal;
738 _val->valueVariant = _val->valueString;
741 _val->valueVariant = QString::fromUtf8( _val->valueByteArray.constData(),
742 _val->valueByteArray.size());
745 _val->valueVariant = QVariant();
748 _haveVariant = isOk2;
754 QVariant retVal = _val->valueVariant;
758 return _val->valueVariant;
764 if (_mutex) _mutex->lock();
766 if (_mutex) _mutex->unlock();
777 ArnLink* link =
this;
780 ArnLink* parentLink = link->parent();
782 if (nameF.is( nameF.
Relative))
break;
783 nameF.set( nameF.
EmptyOk,
true);
785 linkName = link->linkName( nameF);
786 path.insert(0, linkName);
796 QString retVal = convertBaseName( objectName(), nameF);
797 if (this->isFolder() && !nameF.is(( nameF.
NoFolderMark)))
804 uint ArnLink::linkId()
const 812 if (!_hasBeenSetup) {
813 _hasBeenSetup =
true;
814 addSyncMode( syncMode);
817 sendEventsDirRoot( &arnEvLinkCreate, parent());
822 void ArnLink::doModeChanged()
825 sendEventsDirRoot( &arnEvModeChange,
this);
829 ArnLink* ArnLink::findLink(
const QString& name)
831 QString name_ = Arn::convertBaseName( name,
Arn::NameF());
833 int childNum = _children->size();
834 for (
int i = 0; i < childNum; i++) {
835 ArnLink* child = _children->at(i);
837 if (child->objectName() == name_) {
846 bool ArnLink::isFolder(
void)
854 if (_mutex) _mutex->lock();
855 _syncMode |= syncMode.toInt();
856 if (_mutex) _mutex->unlock();
862 if (_mutex) _mutex->lock();
863 int retVal = _syncMode;
864 if (_mutex) _mutex->unlock();
865 return Arn::ObjectSyncMode::fromInt( retVal);
872 if (_mutex) _mutex->lock();
873 mode.set( mode.
Pipe, _isPipeMode);
874 mode.set( mode.
BiDir, _twin != arnNullptr);
875 if (_mutex) _mutex->unlock();
876 mode.set( mode.
Save, isSaveMode());
882 bool ArnLink::isBiDirMode()
884 return _twin != arnNullptr;
888 void ArnLink::setPipeMode(
bool isPipeMode,
bool alsoSetTwin)
890 if (_mutex) _mutex->lock();
891 if (isPipeMode != _isPipeMode) {
892 _isPipeMode = isPipeMode;
893 if (_mutex) _mutex->unlock();
895 if (_mutex) _mutex->lock();
897 if (_twin && alsoSetTwin) {
898 if (_mutex) _mutex->unlock();
899 _twin->setPipeMode( isPipeMode,
false);
900 if (_mutex) _mutex->lock();
902 if (_mutex) _mutex->unlock();
906 bool ArnLink::isPipeMode()
908 if (_mutex) _mutex->lock();
909 bool retVal = _isPipeMode;
910 if (_mutex) _mutex->unlock();
915 void ArnLink::setSaveMode(
bool isSaveMode)
917 ArnLink* link = valueLink();
918 if (
this != link)
return link->setSaveMode( isSaveMode);
920 if (_mutex) _mutex->lock();
921 if (isSaveMode != _isSaveMode) {
922 _isSaveMode = isSaveMode;
923 if (_mutex) _mutex->unlock();
927 if (_mutex) _mutex->unlock();
931 bool ArnLink::isSaveMode()
933 ArnLink* link = valueLink();
934 if (
this != link)
return link->isSaveMode();
936 if (_mutex) _mutex->lock();
937 bool retVal = _isSaveMode;
938 if (_mutex) _mutex->unlock();
943 void ArnLink::setAtomicOpProvider(
bool isProvider)
945 _isAtomicOpProvider = isProvider;
949 bool ArnLink::isAtomicOpProvider()
const 951 return _isAtomicOpProvider;
955 bool ArnLink::isProvider()
const 961 bool ArnLink::isThreaded()
const 963 return _mutex != arnNullptr;
968 void ArnLink::setThreaded()
972 ArnLink* link =
this;
975 link->_mutex =
new QMutex;
977 }
while( link && !link->_mutex);
983 if (_mutex) _mutex->lock();
987 void ArnLink::unlock()
989 if (_mutex) _mutex->unlock();
993 QMutex* ArnLink::getMutex()
const 999 QObject* ArnLink::arnM( QObject* inArnM)
1001 static QObject* storeArnM = arnNullptr;
1003 if (!storeArnM && inArnM)
1009 bool ArnLink::isRetired()
1011 if (_mutex) _mutex->lock();
1012 bool retVal = _isRetired;
1013 if (_mutex) _mutex->unlock();
1018 uint ArnLink::retireType()
1020 if (_mutex) _mutex->lock();
1021 uint retVal = _retireType;
1022 if (_mutex) _mutex->unlock();
1028 void ArnLink::setRetired( RetireType retireType)
1030 if (_mutex) _mutex->lock();
1033 _retireType = uint( retireType);
1036 if (_mutex) _mutex->unlock();
1040 void ArnLink::doRetired( ArnLink* startLink,
bool isGlobal)
1043 if (startLink ==
this) {
1045 sendEventsDirRoot( &arnEvRetired, parent());
1047 ArnEvRetired arnEvRetired( startLink,
false, isGlobal);
1048 sendArnEvent( &arnEvRetired);
1052 ArnLink* ArnLink::twinLink()
1054 if (_mutex) _mutex->lock();
1055 ArnLink* retVal = _twin;
1056 if (_mutex) _mutex->unlock();
1061 ArnLink* ArnLink::valueLink()
1064 ArnLink* retVal = _isProvider ? _twin :
this;
1069 ArnLink* ArnLink::providerLink()
1071 if (_mutex) _mutex->lock();
1072 ArnLink* retVal = _isProvider ? this : _twin;
1073 if (_mutex) _mutex->unlock();
1078 ArnLink* ArnLink::holderLink(
bool useUncrossed)
1080 if (_mutex) _mutex->lock();
1081 ArnLink* retVal = (_twin && !useUncrossed) ? _twin :
this;
1082 if (_mutex) _mutex->unlock();
1087 QString ArnLink::twinName()
1089 QString linkName = objectName();
1092 return linkName.left( linkName.size() - 1);
1095 return linkName +
"!";
1101 void ArnLink::setRefCount(
int count)
1103 ArnLink* vLink = valueLink();
1105 if (vLink->_mutex) vLink->_mutex->lock();
1106 vLink->_refCount = count;
1107 if (vLink->_mutex) vLink->_mutex->unlock();
1111 void ArnLink::decZeroRefs()
1113 int zeroRefCount = 0;
1114 ArnLink* vLink = valueLink();
1116 if (vLink->_mutex) vLink->_mutex->lock();
1117 if (vLink->_zeroRefCount > 0) {
1118 vLink->_zeroRefCount--;
1119 zeroRefCount = vLink->_zeroRefCount;
1121 if (vLink->_mutex) vLink->_mutex->unlock();
1122 if (
Arn::debugLinkRef) qDebug() <<
"link-decZeroRefs: path=" << this->linkPath()
1123 <<
" count=" << zeroRefCount;
1127 bool ArnLink::isLastZeroRef()
1129 bool retVal =
false;
1130 ArnLink* vLink = valueLink();
1132 if (vLink->_mutex) vLink->_mutex->lock();
1133 retVal = (vLink->_refCount == 0) && (vLink->_zeroRefCount == 0);
1134 if (vLink->_mutex) vLink->_mutex->unlock();
1143 ArnLink* vLink = valueLink();
1145 if (vLink->_mutex) vLink->_mutex->lock();
1146 if (vLink->_refCount <= 0)
1147 vLink->_refCount = 1;
1150 if (vLink->_mutex) vLink->_mutex->unlock();
1151 if (
Arn::debugLinkRef) qDebug() <<
"link-ref: path=" << this->linkPath() <<
" count=" << refCount();
1157 if (!subscriber)
return false;
1159 if (_mutex) _mutex->lock();
1163 *_subscribeTab += subscriber;
1164 if (_mutex) _mutex->unlock();
1170 bool ArnLink::unsubscribe(
ArnCoreItem* subscriber)
1172 if (!subscriber)
return false;
1173 if (!_subscribeTab)
return false;
1175 if (_mutex) _mutex->lock();
1176 bool stat = _subscribeTab->removeOne( subscriber);
1177 if (_mutex) _mutex->unlock();
1183 void ArnLink::deref()
1185 bool isZeroRefs =
false;
1186 ArnLink* vLink = valueLink();
1188 if (vLink->_mutex) vLink->_mutex->lock();
1189 if (vLink->_refCount > 1)
1192 vLink->_refCount = 0;
1193 vLink->_zeroRefCount++;
1196 if (vLink->_mutex) vLink->_mutex->unlock();
1197 if (
Arn::debugLinkRef) qDebug() <<
"link-deref: path=" << this->linkPath() <<
" count=" << refCount();
1201 sendEventArnM( &arnEvZeroRef);
1207 int ArnLink::refCount()
1210 ArnLink* vLink = valueLink();
1212 if (vLink->_mutex) vLink->_mutex->lock();
1213 retVal = vLink->_refCount;
1214 if (vLink->_mutex) vLink->_mutex->unlock();
1220 quint32 ArnLink::localUpdateCount()
1224 if (_mutex) _mutex->lock();
1226 retVal = _val->localUpdateCount;
1227 if (_mutex) _mutex->unlock();
Data type of an Arn Data Object
Path: "/@/test" ==> "//test", Item: "@" ==> "".
QList< ArnCoreItem * > ArnCoreItemList
Implies BiDir and all data is preserved as a stream.
Core base class for the inherited ArnItem classes.
virtual ArnEvent * makeHeapClone()=0
Only on path, no effect on discrete names. "/test/value" ==> "test/value".
A two way object, typically for validation or pipe.
Link flags when accessing an Arn Data Object
QByteArray valueByteArray
QThread * thread() const
Get the thread affinity of this ArnCoreItem.
QList< ArnLink * > ArnLinkList
Data is persistent and will be saved.
Only on discrete names, no effect on path. "test/" ==> "test".
volatile ARNREAL valueReal