> Hello again,
I’m sorry for late response,
Next question: In case I created a top level driver with some filtering
realized with CmCalbacks - does it change anything if from usermode I will
do createfile with file_flag_overlapped or not?
Or on what it CAN depend?
Basically from usermode I’m queryging wheter application is able to do
something or not. and I’m doing it in loop (max 3 times) taking
informaiton in 3 different ways (different places) - and quesion is if it
is ok to do this querying with createfile with overlapped io? Is it
possibe (even theoretically that my top level driver will return pending
anyhow? or it will always return what I have in my dispatch IO?
thank you.
First, overlapped I/O is just like regular I/O. The key is tht if you
have an I/O function FIO(h,…) tnen in synchronous mode you can write
A(); FIO(); B(); and get the desired effect. But with async I/O, you
would have to write A(); FIO(h,…); wait(e(h)); B(); which sort of
defeats the purpose of having asynchronous I/O.
The key here is a major paradigm shift: you have to stop associating
sequentiality of execution with sequentiality of syntax. Treat this
concept as largely an artifact of programming prehistory, when “multicore”
meant “we’re going to need two forklifts to get it off the trucks instead
of one forklift to get it off the truck.”
So in the driver, you just fill in te information or set te error code,
and complete the request. You see nothing special to indicate this is
synchronous or asynchronous. Just Do It. An important consideration is
how this request fits into tge sequentiality model of general I/O. For
example, it doesn’t matter if you are asking if the device is capable of
doing something if that is an intrinsic property of the device; it is
always true, or it is always false. You can just complete this request.
No problem. But consider a serial port doing asynchrnous writes. There
are a pending set of writes for the device, W0, W1, …, Wn, where W0 is
the head of the queue. If you DeviceIoControl to change te baud rate, it
changes the baud rate immediately. It might even be in the middle of a
character! So, consider that Wn contained a message to the recipient to
change to a new baud rate. Oopsie. Ok, we’ll wait for Wn to complete.
Unfortunately, te serial driver completes the request after it places the
last character of Wn into the transmit buffer (I hope they fixed this).
At 9600 baud, it takes 3ms to send the character, and on modern machines,
even those of a decade ago (when I had this problem), 3ms was more tan
enough time to respond to the completion request and send the baud rate
change down, and te baud rate change happened in te middle of transmitting
the last character (the checksum). When you do DeviceIoControl, match
them to te logic of your API interface, not to the logic of the device.
Now, consider that you are using an IOCP (the only sane way to do asyc
I/O, in my opinion; straightforward, maximizes concurrency, scales to
large-core environments). You want to do A(); FIO(); B(); where FIO() is
your query. The way to handle this is in a thread. The thread waits for
the completion of FIO() then executes B(). Now you say you are doing te
query in three places. Your pattern is A1(); FIO(); B1(); and somewhere
else, A2(); FIO(); B2(); and A3(); FIO(); B3();. How do you handle this?
The easiest way is to package a function pointer with the OVERLAPPED
structure. Let this be called ovl->F(). So now your sequence is
A1(); ovl->F = &B1(); FIO();
A2(); ovl->F = &B2(); FIO();
A3(); ovl->F = &B3(); FIO();
Now the handler thread is
while(true)
{ /* receiver loop */
OVERLAPPED * ovl;
GetQueuedRequest(…, &ovl, …);
ovl->F();
} /* receiver loop */
Note tat this sketch is at best pseudocode. For example, error checking
and casts are left as an Exercise For The Reader. Also, there is no way
to add anything to an OVERLAPPED structure. Ah, but there is. Consider
te following:
typedef (__stdcall void FIOCONTINUATION *)(…args…);
then we can write
typedef struct {
OVERLAPPED ovl;
FIOCONTINUATION F;
} MYOVERLAPPED;
MYOVERLAPPED * ovl = (MYOVERLAPPED *)malloc(sizeof(MYOVERLAPPED), …);
FIO(h, …, (OVERLAPPED *) ovl;
Note that the MYOVERLAPPED structure can contain any information you need,
such as te infrmation required to pass to F(). Or you can put a complete
struct there, and call F with a pointer to its parameter data.
When I program in C++, I create an abstract superclass:
class B {
virtual void F() PURE;
… stuff
};
class B1 : public B {
virtual void F();
};
repeat above for B2 and B3
Then I can do
typedef struct {
OVERLAPPED ovl;
B* Action;
};
Then I can write
A1(); ovl = new MYOVERLAPPED; ovl->Action = new B1(…); FIO(h, …,
(OVERLAPPED *)ovl);
and in the loop you do
ovl->Action.F();
Key here is to adopt a new paradigm of application construction. In the
driver, you don’t care.
As in the past, much of the casting and error detection and processing are
LAAEFTR. But I’ve built multiple apps using a variety of tese techniques.
What is important to realize is that to convert an app from synchronous
to asynchronous I/O is absolutely NOT a trivial operation; one of the
contracts I didn’t get was a massive piece of trash that I later
discovered was based on a Microsoft example on multithreaded asynchronous
network I/O (other than the fact that the author understood nothing about
asynchronous network connection, threading, or synchronization, there was
nothing wrong with it. I got it nuked from te MSDN examples, and an
analysis of its failure modes and a complete rewrite are on my MVP Tips
Web site. I quoted them a price, and they had no budget to cover that
price. But the rewrite would have been a massive effort.
So don’t worry about what the driver has to do; it doesn’t matter. But
make sure the app isn’t a hacked-together pile of crap as the programmer
tries to warp a synchronous pattern into an asynchronous pattern.
joe
NTDEV is sponsored by OSR
Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
OSR is HIRING!! See http://www.osr.com/careers
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer