Page 6 of 6

Re: To POSIX or not to POSIX

Posted: Sat May 30, 2020 6:08 am
by klange
It's important to note that neither win32 nor POSIX are "designs". Win32 is the result of organic development by a single company, and POSIX is a standard meant to unify many disparate forks of Unix. Much like HTML5, POSIX is written in post, based on the things implementers have done.

Re: To POSIX or not to POSIX

Posted: Sat May 30, 2020 6:43 am
by eekee
I'm a little confused on what async IO actually is, especially when reading. After requesting to read some data, do you poll for it later, or is it delivered by callback, or what?

@klange: I agree. Some of the grafts seem clumsy.

As for threads, I'm never sure whether I want all the threads cluttering up the process list or not. Maybe it would be better if ps made use of process groups.

Re: To POSIX or not to POSIX

Posted: Sat May 30, 2020 6:59 am
by iansjack

Re: To POSIX or not to POSIX

Posted: Sat May 30, 2020 7:20 am
by OSwhatever
nullplan wrote:No, the correct way to do async IO is not to do it at all, but rather use synchronous IO in multiple threads. This also allows for simpler control flow. The only other way to do async IO is to separate the data input path from the data output path (main loop switches between handling read and write). But this only requires a way to test for whether data is ready to be read. Which can also be done with a read() call on a socket that was set to nonblocking, and otherwise only requires a way to sleep until a time has elapsed or data is ready, which select() provides, but so do other things.
I absolutely disagree with that. If you have a server that handles thousands of simultaneous requests you don't want to create a thread context for each client. This is where asynchronous IO shines and you let the operating system services handle the data asynchronously as it is being received/transferred without the extra memory overhead.

Re: To POSIX or not to POSIX

Posted: Sat May 30, 2020 8:16 am
by AndrewAPrice
eekee wrote:I'm a little confused on what async IO actually is, especially when reading. After requesting to read some data, do you poll for it later, or is it delivered by callback, or what?
Any of that. :) It depends on the application.

For something like a single threaded game loop, you could use a message when the data is ready, and process in your gameloop once it's ready (that way the rest of the game can continue running while your data is being read.)

Callbacks are nice, anonymous functions can help with readability by putting the handling code right next to the calling code, but you could end up in nested hell pretty quickly.

Code: Select all

ReadFile(..., (data) => {
   WriteFile(..., () => {
     ReadFile(..., (data) => {
     });
   });
});
A+ promises are better, because you can chain promises together, e.g.

Code: Select all

ReadFile(...).then((data) => {
  return WriteFile(..);
}).then(() => {
  return ReadFile();
}).then((data) => {
});
And you often have functions for joining promises (anyof, allof, etc.)

Await/async can often make this code cleaner and read more sequentially, which can be nice because it makes it easy to do loops and the such:

Code: Select all

data = await ReadFile(...);
await WriteFile(...);
data = await ReadFile(...);
Or you could use a future, which executes the code in another thread/fiber, the waits for it to finish executing when you call .get():

Code: Select all

future_data = MakeFuture(() => {
   data = ReadFile(...);
   WriteFile(...);
   return ReadFile(...);
});
....
data = future_data.get();

Re: To POSIX or not to POSIX

Posted: Mon Jun 01, 2020 6:09 am
by eekee
iansjack wrote:https://en.wikipedia.org/wiki/Asynchronous_I/O
Thanks. I love that article, it's very entertaining to a renegade Wikipedian! :twisted: It's absolutely terrible by Wikipedia standards, but there's some info I recognize as good. So the answer is, "It's all the things, even almost all of the things people refer to as synchronous IO." Okay then.
OSwhatever wrote:If you have a server that handles thousands of simultaneous requests you don't want to create a thread context for each client. This is where asynchronous IO shines and you let the operating system services handle the data asynchronously as it is being received/transferred without the extra memory overhead.
The exact point at which such async IO becomes worthwhile will depend how 'heavy' your thread model is. This raises some questions which might be interesting if they're not too deep even for this board. Also worth remembering: 1000 simultaneous requests was achieved with asyc IO in the 90s. I'm sure modern systems could handle a few thousand without it.

I don't personally anticipate ever having to handle thousands of simultaneous requests, so Plan 9 style lightweight process/threads should be good enough for me, but I've been wondering if another model might be easier to use; lacking deadlock issues. I think I'm paranoid enough to foresee most deadlocks, but I'm never quite as paranoid as I think when it comes to catching bugs. Tired-coding doesn't help.

AndrewAPrice, thanks for your examples! I understand most of the syntax, but what does => do?

Re: To POSIX or not to POSIX

Posted: Mon Jun 01, 2020 7:33 am
by AndrewAPrice
eekee wrote:I understand most of the syntax, but what does => do?
An inlined function in a very pseudo-Javascripty way.

Code: Select all

(function param 1, function param 2 ) => {
   // Function body
}