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 2025 | 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 2025 |
<== Date ==> | <== Thread ==> |
---|
Subject: | RE: multiple threads and ca_attach_context |
From: | "Hill, Jeff" <[email protected]> |
To: | Al Honey <[email protected]>, "'[email protected]'" <[email protected]> |
Date: | Wed, 23 Apr 2014 00:55:57 +0000 |
Aloha Alan, I thought it was my job to jump directly to the source code :-) There are two types of get in CA
1)
A set of ordinary get requests followed by the
pend_io call to synchronize completion 2)
get callback The 1st scenario is applicable only to single threaded (i.e. not in preemptive callback mode) applications.
Each pend IO call is like the rubber bar at the grocery checkout. It separates one set of groceries from another (one set of gets which might have timed out from a subsequent set which have a new chance for success). This type of synchronization is only applicable
in a single threaded execution model. The 2nd scenario works equally well in the single-thread (non-preemptive callback) and preemptive
callback modes but does require more effort in the client side application. In preemptive callback mode the callbacks are fully asynchronous, coming from independent threads for each circuit,
so be careful to protect your data structures using a mutex as appropriate. Jeff From: [email protected]
[mailto:[email protected]] On Behalf Of Al Honey Hi I am unable to determine how to successfully use ca_attach_context, with the creation of multiple threads to read CA channels. I suspect I have missed a step but do not find any relevant documentation.
This is all pertinent to EPICS R3.14.9 Any help would be appreciated. Two scenarios: 1.
Open a connection, via caRepeater, and periodically read the same channel (no problems) 2.
Open a connection, via caRepeater, and periodically launch a posix thread to read the same channel (does not work). Each thread exits after getting a CA channel value. Starting the connection to caRepeater. (code snippets are paraphrased somewhat): static struct ca_client_context *ca_context = NULL; stat = ca_context_create(ca_enable_preemptive_callback); ca_context = ca_current_context(); stat = ca_add_exception_event( exception_callback, NULL ); stat = ca_add_fd_registration( fdReg, NULL); Now launch threads to obtain channel values, in my failure scenario each thread is accessing the same channel. The following occurs for the first thread. // The following is done for both scenarios. // Find the info for the specific channel – details not shown, but essentially an element in an array of structures. If ( info->channelId == NULL ) { stat = ca_create_channel( ch_name, changeConnection_callback, info, 20, &info->channelId); // Do the following as ca_pend_io() returns immediately because a callback was registered with the channel creation. while ( ca_stateinfo->channelId) != cs_conn ) { <a delay with overall timeout> }
// Completes without timeout. } The following is done for each thread (the non-threaded scenario effectively falls thru). If ( ca_context == NULL ) else { my_context = ca_current_context(); if ( my_context != ca_context ) {
// my_context is always nil for each thread and equality for the non=threaded scenario stat = ca_attach_context( ca_context );
// This completes without error for each thread } The following is done whether or not threads are created (both scenarios): stat = ca_get( info->getType, info->channelId, buff );
// This fails with ECA_DISCONN error status in the threaded scenario only. Even with a 3 second delay after ca_get and then retrying ca_get, it fails with disconnected status, in the threaded scenario. If a thread is not created then the above completes successfully (the ca_attach_context logic does not occur in that scenario). Thanks, Allan |