Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
A
ApplicationCore
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
ChimeraTK Mirror
ApplicationCore
Commits
36b136df
Unverified
Commit
36b136df
authored
4 years ago
by
Martin Killenberg
Committed by
GitHub
4 years ago
Browse files
Options
Downloads
Plain Diff
Merge pull request #158 from ChimeraTK/iss130
Merge iss130 branch into master Closes #130
parents
358cd80b
e0847224
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
include/ExceptionHandlingDecorator.h
+9
-2
9 additions, 2 deletions
include/ExceptionHandlingDecorator.h
src/ExceptionHandlingDecorator.cc
+115
-73
115 additions, 73 deletions
src/ExceptionHandlingDecorator.cc
with
124 additions
and
75 deletions
include/ExceptionHandlingDecorator.h
+
9
−
2
View file @
36b136df
...
...
@@ -48,17 +48,24 @@ namespace ChimeraTK {
void
setOwner
(
EntityOwner
*
owner
);
void
doPostRead
(
TransferType
type
,
bool
hasNewData
)
override
;
void
doPostWrite
(
TransferType
type
,
bool
dataLost
)
override
;
void
doPreRead
(
TransferType
type
)
override
;
protected
:
using
ChimeraTK
::
NDRegisterAccessor
<
UserType
>::
buffer_2D
;
DeviceModule
&
deviceModule
;
bool
hasSeenException
{
true
};
bool
previousReadFailed
{
true
};
bool
genericTransfer
(
std
::
function
<
bool
(
void
)
>
callable
,
bool
updateOwnerValidityFlag
=
true
);
void
setOwnerValidity
(
bool
hasExceptionNow
);
boost
::
shared_ptr
<
NDRegisterAccessor
<
UserType
>>
_recoveryAccessor
{
nullptr
};
EntityOwner
*
_owner
=
{
nullptr
};
VariableDirection
_direction
;
bool
transferAllowed
{
false
};
};
DECLARE_TEMPLATE_FOR_CHIMERATK_USER_TYPES
(
ExceptionHandlingDecorator
);
...
...
This diff is collapsed.
Click to expand it.
src/ExceptionHandlingDecorator.cc
+
115
−
73
View file @
36b136df
...
...
@@ -21,8 +21,8 @@ namespace ChimeraTK {
template
<
typename
UserType
>
void
ExceptionHandlingDecorator
<
UserType
>::
setOwnerValidity
(
bool
hasExceptionNow
)
{
if
(
hasExceptionNow
!=
hasSeenException
)
{
hasSeenException
=
hasExceptionNow
;
if
(
hasExceptionNow
!=
previousReadFailed
)
{
previousReadFailed
=
hasExceptionNow
;
if
(
!
_owner
)
return
;
if
(
hasExceptionNow
)
{
_owner
->
incrementExceptionCounter
();
...
...
@@ -34,98 +34,59 @@ namespace ChimeraTK {
}
template
<
typename
UserType
>
bool
ExceptionHandlingDecorator
<
UserType
>::
genericTransfer
(
std
::
function
<
bool
(
void
)
>
callable
,
bool
updateOwnerValidityFlag
)
{
std
::
function
<
void
(
bool
)
>
setOwnerValidityFunction
{};
if
(
updateOwnerValidityFlag
)
{
setOwnerValidityFunction
=
std
::
bind
(
&
ExceptionHandlingDecorator
<
UserType
>::
setOwnerValidity
,
this
,
std
::
placeholders
::
_1
);
bool
ExceptionHandlingDecorator
<
UserType
>::
doWriteTransfer
(
ChimeraTK
::
VersionNumber
versionNumber
)
{
if
(
transferAllowed
)
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doWriteTransfer
(
versionNumber
);
}
else
{
setOwnerValidityFunction
=
[](
bool
)
{};
// do nothing if calling code does not want to invalidate data.
}
while
(
true
)
{
try
{
if
(
!
deviceModule
.
device
.
isOpened
())
{
if
(
Application
::
getInstance
().
getLifeCycleState
()
!=
LifeCycleState
::
run
)
{
// If the application has not yet fully started, we cannot wait for the device to open. Instead register
// the variable in the DeviceMoule, so the transfer will be performed after the device is opened.
assert
(
_recoveryAccessor
!=
nullptr
);
// should always be true for writeable registers with this decorator
return
false
;
}
// We artificially increase the testabel mode counter so the test does not slip out of testable mode here in case
// the queues are empty. At the moment, the exception handling has to be done before you get the lock back in your test.
// Exception handling cannot be tested in testable mode at the moment.
if
(
Application
::
getInstance
().
isTestableModeEnabled
())
{
++
Application
::
getInstance
().
testableMode_counter
;
Application
::
getInstance
().
testableModeUnlock
(
"waitForDeviceOpen"
);
}
boost
::
this_thread
::
sleep
(
boost
::
posix_time
::
millisec
(
DeviceOpenTimeout
));
if
(
Application
::
getInstance
().
isTestableModeEnabled
())
{
Application
::
getInstance
().
testableModeLock
(
"waitForDeviceOpen"
);
--
Application
::
getInstance
().
testableMode_counter
;
}
continue
;
}
auto
retval
=
callable
();
// We do not have to relay the target's data validity. The MetaDataPropagatingDecorator already takes care of it.
// The ExceptionHandling decorator is used in addition, not instead of it.
setOwnerValidityFunction
(
/*hasExceptionNow = */
false
);
return
retval
;
}
catch
(
ChimeraTK
::
runtime_error
&
e
)
{
setOwnerValidityFunction
(
/*hasExceptionNow = */
true
);
deviceModule
.
reportException
(
e
.
what
());
deviceModule
.
waitForRecovery
();
}
return
true
;
/* data loss */
}
}
template
<
typename
UserType
>
bool
ExceptionHandlingDecorator
<
UserType
>::
doWriteTransfer
(
ChimeraTK
::
VersionNumber
versionNumber
)
{
return
genericTransfer
(
[
this
,
versionNumber
]()
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doWriteTransfer
(
versionNumber
);
},
false
);
}
template
<
typename
UserType
>
bool
ExceptionHandlingDecorator
<
UserType
>::
doWriteTransferDestructively
(
ChimeraTK
::
VersionNumber
versionNumber
)
{
return
genericTransfer
(
[
this
,
versionNumber
]()
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doWriteTransferDestructively
(
versionNumber
);
},
false
);
if
(
transferAllowed
)
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doWriteTransferDestructively
(
versionNumber
);
}
else
{
return
true
;
/* data loss */
}
}
template
<
typename
UserType
>
void
ExceptionHandlingDecorator
<
UserType
>::
doReadTransfer
()
{
genericTransfer
([
this
]()
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doReadTransfer
(),
true
;
});
if
(
transferAllowed
)
{
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doReadTransfer
();
}
}
template
<
typename
UserType
>
bool
ExceptionHandlingDecorator
<
UserType
>::
doReadTransferNonBlocking
()
{
return
genericTransfer
(
[
this
]()
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doReadTransferNonBlocking
();
});
if
(
transferAllowed
)
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doReadTransferNonBlocking
();
}
else
{
return
false
;
//hasNewData
}
}
template
<
typename
UserType
>
bool
ExceptionHandlingDecorator
<
UserType
>::
doReadTransferLatest
()
{
return
genericTransfer
(
[
this
]()
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doReadTransferLatest
();
});
if
(
transferAllowed
)
{
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doReadTransferLatest
();
}
else
{
return
false
;
//hasNewData
}
}
template
<
typename
UserType
>
TransferFuture
ExceptionHandlingDecorator
<
UserType
>::
doReadTransferAsync
()
{
TransferFuture
future
;
genericTransfer
([
this
,
&
future
]()
{
future
=
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doReadTransferAsync
();
return
true
;
});
return
future
;
assert
(
transferAllowed
);
if
(
!
transferAllowed
)
{
throw
(
ChimeraTK
::
logic_error
(
"You have to implement ApplicationCore #157"
));
}
return
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doReadTransferAsync
();
}
template
<
typename
UserType
>
...
...
@@ -154,13 +115,19 @@ namespace ChimeraTK {
// Now delegate call to the generic decorator, which swaps the buffer, without adding our exception handling with the generic transfer
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doPreWrite
(
type
);
// #138 Phase 1. Change for phase 2
transferAllowed
=
(
Application
::
getInstance
().
getLifeCycleState
()
==
LifeCycleState
::
run
);
assert
(
Application
::
getInstance
().
getLifeCycleState
()
!=
LifeCycleState
::
shutdown
);
// the waiting is only necessary as a hack for phase 1 because DeviceModule::startTransfer is not there yet
if
(
transferAllowed
)
deviceModule
.
waitForRecovery
();
}
template
<
typename
UserType
>
DataValidity
ExceptionHandlingDecorator
<
UserType
>::
dataValidity
()
const
{
// If there has been an exception the data cannot be OK.
// This is only considered in read mode (=feeding to the connected variable network).
if
(
_direction
.
dir
==
VariableDirection
::
feeding
&&
hasSeenException
)
{
if
(
_direction
.
dir
==
VariableDirection
::
feeding
&&
previousReadFailed
)
{
return
DataValidity
::
faulty
;
}
// no exception, return the data validity of the accessor we are decorating
...
...
@@ -178,11 +145,86 @@ namespace ChimeraTK {
template
<
typename
UserType
>
void
ExceptionHandlingDecorator
<
UserType
>::
setOwner
(
EntityOwner
*
owner
)
{
_owner
=
owner
;
if
(
_direction
.
dir
==
VariableDirection
::
feeding
&&
hasSeenException
)
{
if
(
_direction
.
dir
==
VariableDirection
::
feeding
&&
previousReadFailed
)
{
_owner
->
incrementExceptionCounter
(
false
);
// do not write. We are still in the setup phase.
}
}
template
<
typename
UserType
>
void
ExceptionHandlingDecorator
<
UserType
>::
doPostRead
(
TransferType
type
,
bool
hasNewData
)
{
bool
hasException
=
false
;
try
{
this
->
_target
->
postRead
(
type
,
hasNewData
);
}
catch
(
ChimeraTK
::
runtime_error
&
e
)
{
deviceModule
.
reportException
(
e
.
what
());
hasException
=
true
;
}
// #138 Phase 2: change if codition here
if
(
hasException
)
{
// Try to recover and read until it succeeds.
// We are already behind the delegated postRead, so the transfer in the target is already complemted.
// So we have to use a complete blocking preRead, readTransfer, postRead, i.e. _tagret->read()
while
(
true
)
{
deviceModule
.
waitForRecovery
();
/* //#138 Phase 2
* if (!deviceModule->startTransfer()) continue;
* // end of #138 Phase 2
*/
try
{
this
->
_target
->
read
();
hasException
=
false
;
hasNewData
=
true
;
// if read() returns there is always new data
/* //#138 Phase 2
* deviceModule->stopTransfer());
* // end of #138 Phase 2
*/
break
;
}
catch
(
ChimeraTK
::
runtime_error
&
)
{
/* //#138 Phase 2
* deviceModule->stopTransfer());
* // end of #138 Phase 2
*/
}
}
}
setOwnerValidity
(
hasException
);
// only replace the user buffer if there really is new data
if
(
hasNewData
)
{
for
(
size_t
i
=
0
;
i
<
buffer_2D
.
size
();
++
i
)
buffer_2D
[
i
].
swap
(
this
->
_target
->
accessChannel
(
static_cast
<
unsigned
int
>
(
i
)));
}
}
template
<
typename
UserType
>
void
ExceptionHandlingDecorator
<
UserType
>::
doPostWrite
(
TransferType
type
,
bool
dataLost
)
{
try
{
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doPostWrite
(
type
,
dataLost
);
}
catch
(
ChimeraTK
::
runtime_error
&
e
)
{
deviceModule
.
reportException
(
e
.
what
());
deviceModule
.
waitForRecovery
();
}
}
template
<
typename
UserType
>
void
ExceptionHandlingDecorator
<
UserType
>::
doPreRead
(
TransferType
type
)
{
/* #138 Phase 1. Change this for phase 2 */
/* Hack for phase 1 because DeviceModule::startTransfer is not there yet. */
deviceModule
.
waitForRecovery
();
transferAllowed
=
true
;
// std::cout << "recovered" << std::endl;
// transferAllowed = (Application::getInstance().getLifeCycleState() == LifeCycleState::run);
// auto l = Application::getInstance().getLifeCycleState();
// std::cout << "LifeCycleState: "
// << (l == LifeCycleState::run ? "run" : (l == LifeCycleState::initialisation ? "init" : "shutdown"))
// << std::endl;
// assert(transferAllowed); // not true in phase 2 any more
ChimeraTK
::
NDRegisterAccessorDecorator
<
UserType
>::
doPreRead
(
type
);
}
INSTANTIATE_TEMPLATE_FOR_CHIMERATK_USER_TYPES
(
ExceptionHandlingDecorator
);
}
/* namespace ChimeraTK */
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment