In my c++ windows application I'm using the CreateFile function to access a file. I'm using also the following functions to control my file:
DeviceIOControl
ReadFile
SetFilePointer
since I want that my application will access many positions in the file at the same time (from requests I get to my application) I want that my application will be async. I saw there is a flag for this called FILE_FLAG_OVERLAPPED but I don't know how to use it and when do I know when it complete its operation.
is there any callback that I have to register?
if you can copy here a sample it will be helpful
thanks
You can just spawn a new thread and call ReadFie() synchronously from that second thread. You need to synchronize both threads using a synchronization object, such as an event or a critical section.
If you insist on the single-threaded asynchonous approach, then call the ReadFile() or ReadFileEx() and pass an OVERLAPPED structure. The structure will provide a callback function that will be called once the file read is complete.
However for the callback function to be called, the calling thread (the one that called ReadFile() or ReadFileEx()) has to be in an alertable state.
You just use one of the wait functions to suspend the thread and wait for the read function to call the callback function.
Did you read this MSDN page on Synchronization and Overlapped Input and Output which is describing how it works and linking to the Named Pipe Server Using Overlapped I/O sample?
Related
I'm an intermediate C++ programmer, but I'm new to using Windows' API functions.
I'm trying to create a console program that will sit/sleep until either
The user inputs something in the console and presses enter
Serial data is received on a serial port that's already been opened
Searching around, it sounds like the way to do this in Windows is with Events, (which sound like they're the same basic idea as interrupts?)
I found documentation on the WaitCommEvent, and I've read about reading console input buffer events. I'm guessing the function to use is WaitForMultipleObjects, but what handles specifically do I send it so it will wait for both a serial RX event or a console standard input event?
UPDATE:
Thanks for the response!
Currently I've just been using std::cin/cout to read from and write to the console. I looked over the Console API you mentioned and saw the GetStdHandle function which will give the CONIN$ handle you mentioned. Can I just send that CONIN$handle to the wait function instead of using CreateFile and manually using ReadFile/the Console API like you suggested?
For the Serial, I know how to open my serial handle as OVERLAPPED instead of as NONOVERLAPPED, but I'm not sure what you mean by
it is not usually too difficult to modify synchronous I/O code to use
an asynchronous handle
Something like this?
uint32 read(HANDLE serialHandle, uint8* pBuffer, int32 bufferLenght)
{
DWORD dwBytesRead;
if (!ReadFile(SerialHandle, pBuffer, bufferLength, &dwBytesRead, NULL))
{ /*ERROR*/ }
else
{
// Wait on some flag or variable until read is complete
// to make this call synchronous/NONOVERLAPPED ?
return static_cast<uint32>(dwBytesRead);
}
}
What/where would that flag be to wait on until the read is complete?
From Low-Level Console Input Functions on MSDN:
A thread of an application's process can perform a wait operation to wait for input to be available in an input buffer. To initiate a wait operation, specify a handle to the input buffer in a call to any of the wait functions.
So you need to use a console handle, which you can obtain by calling CreateFile on CONIN$. You will also need to use the same handle, either with ReadFile or the console API, to read the console input; using runtime library functions is likely to mess you up due to buffering.
For the serial port, I believe you will need to use asynchronous I/O. The WaitCommEvent function (when provided with an asynchronous mode handle) accepts an OVERLAPPED structure containing a handle to a manual-reset event object. You would then use the same event handle in the call to WaitForMultipleObjects.
Unfortunately this is an all-or-nothing, so you have to open the COM handle in asynchronous mode and use asynchronous I/O exclusively. (Luckily, it is not usually too difficult to modify synchronous I/O code to use an asynchronous handle, although if there are a lot of I/O calls you might want to write a wrapper function to do the repetitive work of building the OVERLAPPED structure and waiting for the operation to complete.)
I am trying to write a log forwarded for Windows. The plan is simple - receive an event notification and then write it over a TCP socket. This MSDN example shows that I should be using EvtSubscribe. However, I am confused as to how I should share the file descriptor for the open TCP socket. Will the EvtSubscribe callback block by default or will it thread or...?
Thank you in advance for any tips, picking up C++ on Windows after C on Linux has been a bit of a challenge for me :)
The docs are quite sparse in details, but I reckon that it works as follows:
If you use the subscription callback, then it will be called in a dedicated thread. So, if you delay in it, it will block further callbacks, but not other thread of the program
If you use the SignalEvent, it will get signaled when the event arrives, and no threads are created automatically.
You can check that it is really another thread by calling GetCurrentThreadId() from the code that calls EvSubscribe() and from the callback, and compare the values.
My recommendation is to use the thread options, as the Event handlers in Windows are so difficult to be programmed correctly.
About sharing the TCP socket, you can share a socket between threads, but you should not write to it from more than one thread at a time. Nor read.
You can, however, read from one thread and write from another. Also, you can close the socket from one thread while other is in a blocking operation: it will get cancelled.
If you find this limiting, you should create a user thread and use it to send and/or receive data, while communicating with the other threads with queues, or similar.
We have an API that handles event timers. This API says that it uses OS callbacks to handle timed events (using select(), apparently).
The api claims this order of execution as well:
readable events
writable events
timer events
This works by creating a point to a Timer object, but passing the create function a function callback:
Something along these lines:
Timer* theTimer = Timer::Event::create(timeInterval,&Thisclass::FunctionName);
I was wondering how this worked?
The operating system is handling the timer itself, and when it sees it fired how does it actually invoke the callback? Does the callback run in a seperate thread of execution?
When I put a pthread_self() call inside the callback function (Thisclass::FunctionName) it appears to have the same thread id as the thread where theTimer is created itself! (Very confused by this)
Also: What does that priority list above mean? What is a writable event vs a readable event vs a timer event?
Any explanation of the use of select() in this scenario is also appreciated.
Thanks!
This looks like a simple wrapper around select(2). The class keeps a list of callbacks, I guess separate for read, write, and timer expiration. Then there's something like a dispatch or wait call somewhere there that packs given file descriptors into sets, calculates minimum timeout, and invokes select with these arguments. When select returns, the wrapper probably goes over read set first, invoking read callback, then write set, then looks if any of the timers have expired and invokes those callbacks. This all might happen on the same thread, or on separate threads depending on the implementation of the wrapper.
You should read up on select and poll - they are very handy.
The general term is IO demultiplexing.
A readable event means that data is available for reading on a particular file descriptor without blocking, and a writable event means that you can write to a particular file descriptor without blocking. These are most often used with sockets and pipes. See the select() manual page for details on these.
A timer event means that a previously created timer has expired. If the library is using select() or poll(), the library itself has to keep track of timers since these functions accept a single timeout. The library must calculate the time remaining until the first timer expires, and use that for the timeout parameter. Another approach is to use timer_create(), or an older variant like setitimer() or alarm() to receive notification via a signal.
You can determine which mechanism is being used at the OS layer using a tool like strace (Linux) or truss (Solaris). These tools trace the actual system calls that are being made by the program.
At a guess, the call to create() stores the function pointer somewhere. Then, when the timer goes off, it calls the function you specified via that pointer. But as this is not a Standard C++ function, you should really read the docs or look at the source to find out for sure.
Regarding your other questions, I don't see mention of a priority list, and select() is a sort of general purpose event multiplexer.
Quite likely there's a framework that works with a typical main loop, the driving force of the main loop is the select call.
select allows you to wait for a filedescriptor to become readable or writable (or for an "exception" on the filedeescriptor) or for a timeout to occur. I'd guess the library also allow you to register callbacks for doing async IO, if it's a GUI library it'll get the low primitive GUI events via a file descriptor on unixes.
To implement timer callbacks in such a loop, you just keep a priority queue of timers and process them on select timeouts or filedescriptor events.
The priority means it processes the file i/o before the timers, which in itself takes time, could result in GUI updates eventually resulting in GUI event handlers being run, or other tasks spending time servicing I/O.
The library is more or less doing
for(;;) {
timeout = calculate_min_timeout();
ret = select(...,timeout); //wait for a timeout event or filedescriptor events
if(ret > 0) {
process_readable_descriptors();
process_writable_descriptors();
}
process_timer_queue(); //scan through a timer priority queue and invoke callbacks
}
Because of the fact that the thread id inside the timer callback is the same as the creator thread I think that it is implemented somehow using signals.
When a signal is sent to a thread that thread's state is saved and the signal handler is called which then calls the event call back.
So the handler is called in the creator thread which is interrupted until the signal handler returns.
Maybe another thread waits for all timers using select() and if a timer expires it sends a signal to the thread the expired timer was created in.
To simplify, this is a situation where a NamedPipe SERVER is waiting for a NamedPipe CLIENT to write to the pipe (using WriteFile())
The Windows API that is blocking is ReadFile()
The Server has created the synchronous pipe (no overlapped I/O) with blocking enabled
The client has connected, and now the server is waiting for some data.
In the normal flow of things, the client sends some data and the server processes it and then returns to ReadFile() to wait for the next chunk of data.
Meanwhile an event occurs (user input for example) and the NamedPipe SERVER must now execute some other code, which it cannot do while the ReadFile() is blocking.
At this point I need to mention that the NamedPipe Client is not my application, so I have no control over it. I cannot make it send a few bytes to unblock the server. It is just going to sit there and send no data. Since I do not have control of the Client implementation I cannot change anything on that end.
One solution would be to create a separate thread in which all ReadFile() operations are performed. That way when the event occurs, I can just process the code. The problem with that, is that the event also requires a separate thread, so now I have two additional threads for each instance of this server. Since this needs to be scalable, this is undesirable.
From another thread I have tried calling
DisconnectNamedPipe()
and
CloseHandle()
they both will not return (until the client writes to the pipe.)
I cannot connect to the same pipe and write a few bytes because:
"All instances of a named pipe share the same pipe name, but each instance has
its own buffers and handles, and provides a separate conduit for client/server
communication."
http://msdn.microsoft.com/en-us/library/aa365590.aspx
I need a way to fake it out, So the $64k dollar question is:
How can I break the blocking of ReadFile()?
Try this before ReadFile :
BOOL WINAPI PeekNamedPipe(
__in HANDLE hNamedPipe,
__out_opt LPVOID lpBuffer,
__in DWORD nBufferSize,
__out_opt LPDWORD lpBytesRead,
__out_opt LPDWORD lpTotalBytesAvail,
__out_opt LPDWORD lpBytesLeftThisMessage
);
if(TotalBytesAvail > 0)
ReadFile(....);
-AV-
Take a look on CancelSynchronousIo
Marks pending synchronous I/O
operations that are issued by the
specified thread as canceled.
And CancelIo/CancelIoEx:
To cancel all pending asynchronous I/O
operations, use either:
CancelIo — this function only cancels
operations issued by the calling
thread for the specified file handle.
CancelIoEx — this function cancels all
operations issued by the threads for
the specified file handle.
http://msdn.microsoft.com/en-us/library/aa363794(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa365467(VS.85).aspx
Mike,
You can't cancel synchronous ReadFile. But you can switch to asynchronous (overlapped) operations. By doing this, you can implement a pretty scalable architecture.
Possible algorithm (just an idea):
For each new client call ReadFile
WaitForMultipleObjects where the handles are overlapped.hEvent + your
custom events
Iterate over signalled events, and schedule them for execution by threads from a threads pool.
This way you can have only few threads to receive connections and read data, while the actual data processing can be done by the threads pool.
The problem with that, is that the
event also requires a separate thread,
so now I have two additional threads
for each instance of this server.
Since this needs to be scalable, this
is undesirable.
Never in my career have I found that "more threads" == "less scalable". How many of these "server" instances do you have?
Normally, an operation needs to be performed in a separate thread if that operation is going to block and the system needs to be responsive while the operation is blocked.
Asynchronous I/O operations do not have to block any thread if they use I/O Completion Ports. See: http://msdn.microsoft.com/en-us/library/aa365198(VS.85).aspx
What happening is the server outbound pipe is left open waiting for connection while your client is trying to connect to the server inbound pipe (which is no longer existent)... What you need to do is flush out your outbound pipe in order to loop back to your inbound. You can flush out on the client side by reading the file (remember to loop the connect establishment because there is a "handshake" in there, and it will never work the first time)
Just use SetNamedPipeHandleState function
https://learn.microsoft.com/en-us/windows/win32/api/namedpipeapi/nf-namedpipeapi-setnamedpipehandlestate
Use the PIPE_NOWAIT flag when calling this function.
hNamedPipe should be the handle that returned from CreateFile function.
After that, the call to ReadFile will not block the thread when no data available.
I want to monitor the modifications in a specified directory, and retrieve the exact change information. So I've decided to use the ReadDirectoryChangesW() function. But I want to use it asynchronously, which means I don't want my worker thread to be blocked if there are no changes in the directory.
How can I do this?
I tend to use ReadDirectoryChangesW() with an I/O Completion Port, which is good for when you want to monitor multiple directories because you can have a single thread servicing the IOCP and dealing with the results from all of your calls to ReadDirectoryChangesW().
First create an IOCP, once, by calling CreateIoCompletionPort(). Start a thread that calls GetQueuedCompletionStatus() and deals with your async directory changes.
Now for each directory that you want to monitor. First, open your directory handle as normal. Next, associate it with your IOCP by calling CreateIoCompletionPort() and passing the IOCP handle in (see docs for more details). Finally, call ReadDirectoryChangesW() and pass an OVERLAPPED as detailed in the docs. The call will return, and if successful, the results will become available as the results of GetQueuedCompletionStatus() in the thread that you created to service the IOCP.
From the MSDN documentation for ReadDirectoryChnagesW():
For asynchronous completion, you can receive notification in one of
three ways:
Using the GetOverlappedResult function. To receive notification
through GetOverlappedResult, do not
specify a completion routine in the
lpCompletionRoutine parameter. Be sure
to set the hEvent member of the
OVERLAPPED structure to a unique
event.
Using the GetQueuedCompletionStatus function. To
receive notification through
GetQueuedCompletionStatus, do not
specify a completion routine in
lpCompletionRoutine. Associate the
directory handle hDirectory with a
completion port by calling the
CreateIoCompletionPort function.
Using a completion routine. To receive notification through a
completion routine, do not associate
the directory with a completion port.
Specify a completion routine in
lpCompletionRoutine. This routine is
called whenever the operation has been
completed or canceled while the thread
is in an alertable wait state. The
hEvent member of the OVERLAPPED
structure is not used by the system,
so you can use it yourself.