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 | 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 |
<== Date ==> | <== Thread ==> |
---|
Subject: | RE: Multithreading in R3.14.9 - preemptive callbacks not working. |
From: | "Jeff Hill" <[email protected]> |
To: | "'Douglas Morrison'" <[email protected]>, <[email protected]> |
Date: | Wed, 21 Jan 2009 08:33:52 -0700 |
Hello Doug, I suspect that it will work as you were expecting in the first
program if you add a ca_flush call after the ca_add_event call. Let me know if
that doesn’t take care of it and I will have a closer look. Jeff Hill From:
[email protected] [mailto:[email protected]] On
Behalf Of Douglas Morrison Hello, I
am running EPICS R3.14.9 on a Solaris 10 machine, and am having difficulties
implementing a multithreaded event monitoring application. The goal is for the
main thread to open channel connections, and wait for user commands to perform
other tasks. An auxiliary thread would be responsible for processing channel
events as they occur. I
have read in the 3.14 users manual that when the context is created using
ca_enable_preemptive_callback, the CA library will spawn auxiliary threads that
will automatically execute event callbacks. I use the following code to open a
channel and set a callback (error handling removed for brevity): void
connect_handler(struct connection_handler_args connect_args) {
// Handle connection
events. } void
event_handler(struct event_handler_args event_args) {
// Print data. } int
main(…) {
chid chId;
int stat;
stat = ca_context_create(ca_enable_preemptive_callback);
stat= ca_create_channel(argv[1], connect_handler, argv[1], 49, &chId);
// Give the connect request time to process
ca_pend_event(0.05);
stat=ca_add_event(DBR_DOUBLE, chId, event_handler, NULL, NULL);
sleep(10.0); } Based
on what I’ve read, I would expect that while the main thread is sleeping, the
CA auxiliary threads would be finding events and executing the callback,
however it never does (the actual database value is update at 2 Hz). Is my
understanding or setup of the CA connections incorrect for this usage? As
a fix, I acquire the ca_context right after I create it, and attach an
application thread to the context which is responsible for executing periodic
polling (again, error checking removed for brevity): struct
ca_client_context* caContext = NULL; void*
dispatcher(void* ctx) {
stat = ca_attach_context(caContext);
while(1) {
ca_pend_event(0.0001);
sleep(0.5);
}
return NULL; } int
main(…) {
…
stat = ca_context_create(ca_enable_preemptive_callback);
caContext = ca_current_context();
…
pthread_create(&dispatchThread, NULL, dispatcher, NULL);
sleep(10.0); } Using
this setup I successfully get callback events. Did I misunderstand the
documentation when it said the CA Library would create its own event processing
threads, and that the second method I emply is actually the correct method? Final
question: When using preemptive callbacks, performing a select on the file
descriptors created by channel connections no longer see any change on the
sockets. Why is this (what is the motivation)? Any
help would be greatly appreciated. Douglas A. T. Morrison Software Engineer C.A.R.A - W. M. Keck Observatory 65-1120 Mamalahoa Hwy. Kamuela, HI. 96743 Office: (808)881-3539 Cell: (808)937-0998 |