On 19/05/2004 at 9:00 AM, Scott Hannahs <[EMAIL PROTECTED]> wrote: > At 7:58 -0500 5/19/04, [EMAIL PROTECTED] wrote: >> If the task acquires a finite number of samples and you set this >> input to -1, the VI waits for the task to acquire all requested >> samples, then reads those samples. > > Is this a blocking wait like the non-DAQmx call into a CIN (or LLB) or > is it a "LV style" wait where other LV nodes even in the same thread > can execute? That would be nice! Is there a way to do this threading > in our own created dlls (frameworks)?. I would like to make my PCI- > GPIB library non-blocking but that is not trivial because of this > limitation. Is there a way to set up a call back into LV for a non- > blocking wait from a CIN or framework?
I'm not sure exactly what you are asking; so, I'll define some terms, explain a couple of things, and hope I get lucky :) For example, I'm not sure what you mean by a "LV style" wait. I'm not aware of a construct that would allow a thread to wait on a synchronization primitive and yet continue to execute. That is, a thread is either running or waiting. If my definition of an asynchronous call matches your definition of a "LV style" wait, great. If not, please let me know what you have in mind. So, here are some definitions that I'll use. Note that these aren't necessary standard definitions, but I'll use them is this mail: Synchronous call: the thread that invokes the call performs the specified operation in its entirety. When the calling thread has returned to its originating context, the operation has been completed either successfully or unsuccessfully. Most VIs, including the DAQmx Read VI, operate in this fashion. Asynchronous call: the thread that invokes the call doesn't perform the specified operation in its entirety but, rather, schedules another thread to perform the operation. When the calling thread has returned to its originating context, the operation may or may not have been completed. Usually, there is a mechanism where either the scheduled thread "calls back" to inform the application of the status of the operation or the calling thread can invoke another call to check on the status of the operation. Few VIs operate in this fashion. From a certain perspective, the DAQmx Write VI operates in this fashion when performing a generation timed by a method other than on-demand timing. That is, the DAQmx Write VI may return before all samples are generated. The DAQmx Is Task Done VI is used to query the status of this asynchronous operation. (The validity of this example is dependent on the perspective that the operation performed by the DAQmx Write VI is to generate all samples from the device rather than to only copy the samples to the device.) These two types of calls present fundamentally different API models. In general, synchronous calls cannot simply be converted to asynchronous calls without changing the semantics of the API and adding additional concepts (e.g., call backs, query calls). Regardless of the type of call, other threads in the application may continue to execute. There are at least a couple of factors that determine how these other threads may be constrained by the thread making the call. One factor is how the synchronous call waits. If the thread is continuously trying to execute code to check the status of a pending operation (i.e., polling), other threads will be competing with this thread for the processor. However, if the thread waits on a synchronization primitive, other threads will not be competing with this thread until this synchronization primitive is signaled and the thread is awakened. The polling approach is more responsive (i.e., the change in status is detected more quickly) and less efficient (i.e., the processor is used more) than the thread waiting on a synchronization primitive. The DAQmx Read VI falls somewhere between these two extremes in an attempt to balance responsiveness and efficiency. A second factor relates to what kind of locks are acquired by the call (either a synchronous or asynchronous call). A call that acquires a very general lock that other threads in the system may need (e.g., Traditional NI-DAQ VIs that acquire a lock for all of Traditional NI-DAQ) will prevent any other threads from acquiring that same lock; these other threads will wait for the lock to be released. However, a call that acquires a more specific lock (e.g., DAQmx VIs that acquire a lock for a specific task) will only prevent other threads that try to acquire that specific lock from executing. While I'm certainly not an NI-488.2 expert, I believe there are both synchronous and asynchronous functions in NI-488.2. Regardless, other threads in your application should be able to execute while a NI-488.2 call is waiting subject to the restrictions I've mentioned. If you're concerned that your PCI-GPIB library is too inefficient when waiting and it is polling, maybe you can change its implementation such that the thread waits on a synchronization object rather than polls (or at least occasionally yields to give other threads more of a chance to use the processor). If you're concerned that other threads in your application cannot execute because the thread that is waiting has acquired a common lock, perhaps the lock can be eliminated or a finer-grained lock can be used instead. If you really want other LV nodes to be executed by the same thread that is calling into your library, you need to structure your API to be asynchronous and provide other mechanisms to communicate the status of these asynchronous operations. I hope this helps. geoff -- Geoffrey Schmit Senior Software Engineer National Instruments [EMAIL PROTECTED] www.ni.com
