Beta version of async stuff!

Monkey Archive Forums/Monkey Discussion/Beta version of async stuff!

marksibly(Posted 2012) [#1]

There's a beta version of the new async TCP stuff up! Replace your brl modules in V64 with this:

There's an HTTPGetter in brl/bananas, tested successfully on glfw/android/ios. Note how you can smoothly scroll the page while it's loading...ooh ahh!

A quick rundown on the various read/write methods of AsyncStream:
Method Read:Void( data:DataBuffer,offset:Int,count:Int,onComplete:IOnReadComplete )

Perform a single read. Will read at least 1 byte unless EOF.

Method ReadAll:Void( data:DataBuffer,offset:Int,count:Int,onComplete:IOnReadAllComplete )

Read continuously until either count bytes are read or EOF.

Method ReadChunk:Void( data:DataBuffer,offset:Int,count:Int,format:Int,onComplete:IOnReadChunkComplete )

Read length, followed by length bytes. Completely untested!

Method Write:Void( data:DataBuffer,offset:Int,count:Int,onComplete:IOnWriteComplete )

Perform a single write. Will probably, usually, maybe always write all bytes. But just in case, use this instead...

Method WriteAll:Void( data:DataBuffer,offset:Int,count:Int,onComplete:IOnWriteAllComplete )

Write continuously until count bytes are sent.

Method WriteChunk:Void( data:DataBuffer,offset:Int,count:Int,format:Int,onComplete:IOnWriteChunkComplete )

Write count, followed by count bytes. Completely untested!

Method Update:Bool()

Invokes any pending completion handlers. Return true if any were invoked.

See ascynstream.monkey for more info on what gets passed to the completion handlers.

It all looks horribly complex, but as long as your databuffers are big enough a lot of it can be ignored.

A lot of the detail in there is mostly for the sake of a potential future AsyncStreamBuffer that streams into an internal dynamically resizing buffer and can handle partial chunk reads etc.

But these low level methods are 100% New-free, and I think it's good that way - not only does it mean you can write New-free code with them, but it splits the whole dynamic buffering problem into 2 distinct bits.

A lot of the AsyncTCPStream implementation could actually be moved to the base AsyncStream class, and reused with a filestream (for streaming audio/video) and perhaps even an audiostream (for creating/capturing audio data on the fly!).

AscyncTCPStream can also run in full duplex or half duplex mode. Full duplex (the default) requires 2 threads. Half duplex only requires one thread, but reads/writes must happen in sequence - ie: you can't read/write data at the same time. The HTTP getter can work in half duplex mode due to the way the HTTP protocol works, but for gaming full duplex is probably the way to go.

Finally, the burning question of the day - should it be TCPStream, AsyncTCPStream etc or TcpStream/AsyncTcpStream? I think I prefer the latter!

Have fun!

Skn3(Posted 2012) [#2]
Holy crap wow! This is brilliant, it's like the monkey beta days :) will def be giving this a try at some point this week. Good stuff Mark.

Oh and I prefer TcpStream even if technically it should be TCPStream. I find it is easier to type using less capitol letters when mixed in camel case.

marksibly(Posted 2012) [#3]

Thinking about it now, the ReadChunk/WriteChunk methods may end up being moved to a 'buffer' class - I'll know more once I write it!

marksibly(Posted 2012) [#4]

Ok, I just got an AsyncBuffer going that wraps an AsyncStream.

This extends stream, so you now get synchronous access to async streams!

The only thing you need to be careful of is using ReadInt() etc when ReadAvail() returns <4 etc. If you do this, they'll throw an exception.

I now think chunks should probably be left out of things altogether, since you can now 'poll' for them. Since you effectively have to poll streams anyway via Update(), I don't think this is a huge loss.

I might also collapse Read/ReadAll and Write/WriteAll into single methods, and add an 'all' param to each, so AsyncStream only has Read/Write.

Sound OK?

Tibit(Posted 2012) [#5]
Awesome, this is just great! I feel happy to feel spoiled to be a Monkey programmer and having so frequent updates :)

Going to be fun to dive into more networking today!

> Read/ReadAll and Write/WriteAll into single methods
I agree

> I now think chunks should probably be left out of things altogether
For the basics of tcp networking chunks are not needed, imo Chunks are a higher level (though only slightly higher) feature, but so are ping, disconnect and many others. Maybe better if it also is built on a higher level? I'm going to take a closer look at the Chunk system today, does it mean I do not need a TCP-Stream-Packetizer on the monkey side of things?

> Ok, I just got an AsyncBuffer going that wraps an AsyncStream.
Updates happening so quickly around here! Intuitively sounds to me like the right way to go.

marksibly(Posted 2012) [#6]

Upon reflection, I don't think the above system is too bad!

Having chunks built in to AsyncStream may not be necessary, but I guess it doesn't hurt, and it's probably the most efficient way to read them without having to buffer/copy data around. Although it requires 2 socket reads, data goes directly from the socket buffer to your data buffer - and socket data is already buffered so I think the extra read is probably worth it.

I'm starting to think AsyncBuffer may not be such a hot idea though (and I spent all day on it!) as you could achieve the same thing with a plain TcpStream if it had ReadAvail (it probably will). Either way, you're effectively polling, only in a very round about way with the AsyncBuffer. I also prefer the overall OnComplete approach to receiving data in general - it's just tidier than polling.

Anyway, experiment away and let me know what you think.

Skn3(Posted 2012) [#7]
I had a quick look at the source last night and saw that you have massive thread warnings about not being thread safe. What is the realistic scope for monkey threading in the future?

The js/as is also obviously just place holder for the tcp stuff at the moment but do you see yourself writing a websocket server to handle these targets?

So let me get this straight, you can get notifications asynchronously about the status of individual reads and writes on a buffer? So I could trigger buffer.ReadInt() or buffer.WriteInt(5) but what callbacks/notifications will get called from start to finish?

Skn3(Posted 2012) [#8]
Hey I wrote a little demo using the new beta code.

It also uses the new pixel commands. Two birds one stone...

The only issues I cam across was that the Http getter buffer sizes were not large enough. Also I had to amend the httpgetter code to accept a full blown url with path and query.

Xaron(Posted 2012) [#9]
That is great, Mark! :)

Any chance to get that streaming stuff for C# as well? Especially for the coming Windows 8 target?