Dear Tom,
I could finally solve my problem. Everything was correct except a very simple stupid problem. I had a flushio called periodically, even when nothing had to be flushed. In this case a default context is created by EPICS, which prevent my recreating a context as preemptive. This happened while many different threads are used.
The way you did the things, persuaded me to stay on the problem. Thank you very much.
Best regards
Anton
-----Original Message-----
From: Pelaia II, Tom [mailto:[email protected]]
Sent: Dienstag, 17. Februar 2015 17:23
To: Mezger Anton Christian (PSI)
Subject: Re: epics problem on ios
Hi Anton,
I have success closing channels upon entering background and connecting them upon entering foreground. I don't experience the issue you are having. However, based on what you said, I don't see a problem with what you are doing. Below I've posted relevant code that hopefully may help. The full code is available on Source Forge at ( http://sourceforge.net/projects/capod/ ), but Source Forge is currently offline now.
In my app delegate, I have the following relevant code:
// handle the event of the application entering the background
- (void)applicationDidEnterBackground:(UIApplication *)application {
[_managedObjectContext save:nil];
self.channelOpenBeforeBackground = self.probeModel.active; // record whether channel access was active prior to entering background
[_probeModel closeChannelAccess];
}
// application has resumed from being in the background
- (void)applicationWillEnterForeground:(UIApplication *)application {
if ( self.channelOpenBeforeBackground ) [self.probeModel openChannelAccess]; }
I also create the channel access context upon entering the foreground and destroy it upon entering the background.
My Probe Model code has the following relevant code:
- (void)openChannelAccess {
if ( !self.active ) {
// construct the address list
[self setupAddressList];
// create a new CA context
[ChannelAccessContext prepare];
// startup the channels
NSArray *channels = [self.managedObjectContext executeFetchRequest:self.channelFetchRequest error:nil];
for ( ProbeChannel *channel in channels ) {
[self monitorChannel:channel];
}
[ChannelAccessChannel flushIO];
self.active = YES;
}
}
- (void)closeChannelAccess {
if ( self.active ) { // check whether there is anything to close
self.active = NO;
// shutdown the channels
NSArray *channels = [self.managedObjectContext executeFetchRequest:self.channelFetchRequest error:nil];
for ( ProbeChannel *channel in channels ) {
[channel removeObserver:self forKeyPath:@"latestRecord"];
[channel destroyProbe];
}
[ChannelAccessChannel flushIO];
// destroy the current CA context
[ChannelAccessContext destroy];
}
}
- (void)setupAddressList {
NSArray *channelAddresses = [self.managedObjectContext executeFetchRequest:self.addressFetchRequest error:nil];
NSString *addressList = [ChannelAddress channelAddressList:channelAddresses];
[ChannelAccessContext setAddressList:addressList]; }
My Channel Access Context
+ (void)prepare {
// create a new context if one does not already exist if ( !ca_current_context() ) { ca_context_create( ca_enable_preemptive_callback ); } }
+ (void)destroy {
if ( ca_current_context() ) {
ca_context_destroy();
}
}
// get the space delimitted string of channel addresses
+ (NSString *)addressList {
return @( getenv( CA_ADDRESS_LIST_ENVIRONMENT_LABEL ) ); }
// set the space delimitted string of channel addresses
+ (void)setAddressList:(NSString *)addressList {
// work with an immutable copy of the passed address list in case the passed string is mutable and changes NSString *localAddressList = [addressList copy];
char * autoAddr = localAddressList != nil && [localAddressList length] > 0 ? "NO" : "YES"; setenv( "EPICS_CA_AUTO_ADDR_LIST", autoAddr, 1 );
if ( localAddressList != nil && [localAddressList length] > 0 ) { NSUInteger bufferSize = ( [localAddressList length] + 1 ) * sizeof( char ); char *buffer = (char *)malloc( bufferSize ); [localAddressList getCString:buffer maxLength:bufferSize encoding:[NSString defaultCStringEncoding]]; setenv( CA_ADDRESS_LIST_ENVIRONMENT_LABEL, buffer, 1 ); free( buffer ); } else { unsetenv( CA_ADDRESS_LIST_ENVIRONMENT_LABEL ); } }
Best regards,
Tom
_____________________________________________________________________________________
Thomas Pelaia II, Ph.D. | Applications Leader, Accelerator Physics, Research Accelerator Division Spallation Neutron Source | Oak Ridge National Lab, Building 8600, MS-6462, Oak Ridge, TN 37831
phone: (865) 414-7960 | FaceTime: [email protected]<mailto:[email protected]> | fax: (865) 574-6617 | homepage: http://www.ornl.gov/~t6p
On Feb 14, 2015, at 6:50 AM, Mezger Anton Christian (PSI) <[email protected]<mailto:[email protected]>> wrote:
Dear Tom,
I made some tries.
when the application goes into the background and comes to the foreground again, I do not need to do anything, The channels stay connected (on Ipad, not on Iphone). However when the application goes in suspended mode, the socket gets closed.
In order to come around this, I delete all the channels and close the context. Afterwards I create the context again. This does not work, while I get the error message that preemptive callback can not be enabled. When creating then the channels, I get no connections.
How did you solve that? It seems to me that in an application it is not best to create a context, delete it and create it again with preemptive callback.
I hope you have a solution !
best regards
Anton
- Navigate by Date:
- Prev:
Re: Read record field in asynDriver Ralph Lange
- Next:
RRM offline? Benjamin Franksen
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
<2015>
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
epics on ios Mezger Anton Christian (PSI)
- Next:
medm3.1.8 linker problem yann stephen
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
<2015>
2016
2017
2018
2019
2020
2021
2022
2023
2024
|