monitoring multiple I/O handles.

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

monitoring multiple I/O handles.

Post by Pype.Clicker »

For those who knows "select" system call in POSIX, i'm facing that: designing a proper interface to a "select"-like operation. I shall admit i never was very enthusiast at the way select works, how it requires you to built and maintain a bitmap of monitored descriptors and how it rewrites your bitmap with the list of file handles that are readable/writable.

I once thought clicker would rather have system calls like

Code: Select all

  CommPort.recv(&msg); // locks until a message arrives
  CommPort.monitor(OtherCommPort);
  CommPort.monitor(YetAnotherCommPort);
  ReadyPort=CommPort.recv(&msg);
     // monitors both CommPort, OtherCommPort and YetAnotherCommPort and tells which one has been read.


Yet, at the point of implementing it, i now doubt of my choice... Okay, "select" is somehow boring because - in user mode - you have to scan the bitmap to know what descriptor you can read on. that's common to see code like

Code: Select all

    while (1) {
        // memcpy the whole bitmap under the hook
        ready_fds=read_fds;
        readies=select(max_fd,&ready_fds,...);
        for (i=0;i<max_fd;i++) {
           if (!readies) break; // we're all done.
           if (FD_ISSET(ready_fds,i)) {
              do_stuff_with_fd(i);
              readies--;
           }
         }
     }


which is (imho) one of the ugliest piece of Unix code i can think of ... Yet it has many benefits over my own proposal, for instance it nicely supports priorities amongst the files. e.g. if you decide that file descriptor X should be checked before any of the other, you can just do it in pure user mode. the kernel do not need to be aware of the policy you apply.

So would it make sense to have one API that simply applies FIFO policy and assume everyone will be happy with that, but that where the kernel acts like an "enumerator" of ready handles and one API that returns a bitmap and then let the user code do whatever it wants with that ?

Anyone has experience with a similar API in non-unix systems ?
Rob

Re:monitoring multiple I/O handles.

Post by Rob »

I'm not sure I'm following what it is exactly that you are talking
about. I only have experience on the Windows platform. The
only thing I can think of that might be something you are looking at is:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waitformultipleobjects.asp

Or I'm not following what you are talking about :)
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:monitoring multiple I/O handles.

Post by Pype.Clicker »

Rob wrote:I'm not sure I'm following what it is exactly that you are talking
about. I only have experience on the Windows platform.


that's more or less the idea. Unix call is limited to file handles (though as everything is supposed to be a file in unix, there's no reasons you might want to wait for anything else ::) ) while windows obviously allow many more objects to be wait'd for ... though

Code: Select all

for (i = 0; i < 2; i++) 
{
    hEvents[i] = CreateEvent(
        NULL,   // default security attributes
        FALSE,  // auto-reset event object
        FALSE,  // initial state is nonsignaled
        NULL);  // unnamed object

    if (hEvents[i] == NULL)
    {
        printf("CreateEvent error: %d\n", GetLastError() );
        ExitProcess(0);
    }
}

// The creating thread waits for other threads or processes
// to signal the event objects.

dwEvent = WaitForMultipleObjects(
    2,           // number of objects in array
    hEvents,     // array of objects
    FALSE,       // wait for any
    INFINITE);   // indefinite wait

// Return value indicates which event is signaled.

switch (dwEvent)
{
    // hEvent[0] was signaled.
    case WAIT_OBJECT_0 + 0:
        // Perform tasks required by this event.
        break;

    // hEvent[1] was signaled.
    case WAIT_OBJECT_0 + 1:
        // Perform tasks required by this event.
        break;

    // Return value is invalid.
    default:
        printf("Wait error: %d\n", GetLastError());
        ExitProcess(0);
}


is probably even uglier than unix's select to my eyes (yet, my eyes might be biased).

Thanks for mentionning it.
Rob

Re:monitoring multiple I/O handles.

Post by Rob »

If you have the bandwidth and are able to play Windows Media files I suggest you check a movie on a concurrency research project going on in Microsoft that might give you some ideas on how to handle multiple "events":

http://channel9.msdn.com/ShowPost.aspx?PostID=143582

It's an interesting movie, but the main guy talking seems to have a bit of ADD or something, but it's worth taking that beating... :)

p.s. you can download it (to watch offline etc.)
Rob

Re:monitoring multiple I/O handles.

Post by Rob »

I think you can mimic Unix's select in Windows, by doing something like (with MS' example above):

Code: Select all

for (int i = 0; i < 2; i ++)
{
???if (WAIT_OBJECT_0 + i == dwEvent)
???{
??????do_stuff_with_fd(i);
??????i = 2; // or whatever
???}
}


Or did you mean the setup of the wait? I think you can re-use it, but I'm not sure. You may need to "reset" the handle (which is what everything in Windows is called) though
JoeKayzA

Re:monitoring multiple I/O handles.

Post by JoeKayzA »

Ok, my proposal might seem awkward or not appropriate to you, but I don't know that much about clicker's internals and how you handle system calls.

For me I plan to implement as many system calls as possible (if not all) in an asynchronous way - in fact a bit like lightweight messages, only that they go from usermode to kernelmode, not between usermode processes. Thus, every object which can receive system calls is some kind of 'message port' (it's an object handle, in clicker terminology you would call it 'resource', IIRC). Furthermore, you can group together multiple object handles to form a 'collection', which is a seperate handle itself, and you can wait on the whole collection.

This seems to be a bit similar to what you wrote in your initial post, the only difference is that you wouldn't use 'CommPort' to monitor both 'AnotherCommPort' and 'YetAnotherCommPort'. You would rather build a seperate object, which monitors all of them.

Actually, this system is taken from the Mach microkernel.

cheers Joe
User avatar
Pype.Clicker
Member
Member
Posts: 5964
Joined: Wed Oct 18, 2006 2:31 am
Location: In a galaxy, far, far away
Contact:

Re:monitoring multiple I/O handles.

Post by Pype.Clicker »

well, i suppose having "Portcollection" object makes sense too ... in my case, any port could be "promoted" to a collection, but i have to admit i can't remind of why i dismissed the idea of a "Collection" class ... probably i didn't wish yet-another-resource-slot-consumed.
Post Reply