RejectedSoftware Forums

Sign up

Pages: 1 2 3

Status of Win32 version (listenTcp, etc)

I've been writing a game server using D2 for a little while as a project in my spare time and just recently stumbled across Vibe.d. The awesome thing is that the design you guys have done with fibering and events is almost exactly what I use as well in my current implementation! Definitely "the only" good way to write async code IMHO.

Thus I was thrilled to find Vibe.d and plug it into my implementation, reduce my application code, and get access to some of Vibe's fancier features. While I don't need to serve HTTP at the moment for instance, I do need to make HTTP requests (currently through CURL), and it might be handy in the future to do both.

Porting my code took <1hr since it was already very similar in structure to how vibe works. That said when I went to run it, I discovered that there seems to be a bunch of missing functionality on Win32 at the moment, which I'm using as my primary development platform currently. In the release version requestTcp hit some assert(false)'s and while that now works once I updated to the top of tree, listenTcp (really my only other required feature in the short term) does not.

Thus I wanted to ask about the plans and timeframe for finishing up some of these features in the Win32 implementation. I'm excited to switch to using Vibe.d instead of my current, less feature-ful implementation and thus I'm curious when might be a good time to check back :)

Thanks for all your hard work! It's also great to see the system design validated by a full-fledged project :)

Re: Status of Win32 version (listenTcp, etc)

On Sun, 16 Dec 2012 03:21:26 GMT, punkUser wrote:

I've been writing a game server using D2 for a little while as a project in my spare time and just recently stumbled across Vibe.d. The awesome thing is that the design you guys have done with fibering and events is almost exactly what I use as well in my current implementation! Definitely "the only" good way to write async code IMHO.

Nice! I fully agree, this combination D+async I/O+fibers was something I've missed for quite some time until finally deciding to give it a go and make it a reality (I think the trigger was being forced to use the callback based API of node.js, which really turned me off). But some people for some reason think, that an evented programming is actually the advantage of asynchronous I/O - probably because they have never used both models.

Thus I was thrilled to find Vibe.d and plug it into my implementation, reduce my application code, and get access to some of Vibe's fancier features. While I don't need to serve HTTP at the moment for instance, I do need to make HTTP requests (currently through CURL), and it might be handy in the future to do both.

Porting my code took <1hr since it was already very similar in structure to how vibe works. That said when I went to run it, I discovered that there seems to be a bunch of missing functionality on Win32 at the moment, which I'm using as my primary development platform currently. In the release version requestTcp hit some assert(false)'s and while that now works once I updated to the top of tree, listenTcp (really my only other required feature in the short term) does not.

Thus I wanted to ask about the plans and timeframe for finishing up some of these features in the Win32 implementation. I'm excited to switch to using Vibe.d instead of my current, less feature-ful implementation and thus I'm curious when might be a good time to check back :)

Did you dig in far enough to explicitly enable the win32 back end or did you use the VisualD project? I'm asking because if the server is supposed to be command line only, the default libevent back end should work fine on Windows (for the VisualD project this would require removing the VibeWin32Driver version in the Compiler/General section).

The win32 back end is currently developed in parallel to a larger project that needs it because it offers Windows event loop integration and a directory watcher. This is why it currently only has the features needed by that project. However, I wanted to get it completed for the next release (it would still be "beta" in that case regarding possible bugs and high-throughput performance). So if everything goes as desired, that would mean around the end of this month.

Thanks for all your hard work! It's also great to see the system design validated by a full-fledged project :)

Yes, it was also really nice for me/us to see how well the idea turned out in reality!

Re: Status of Win32 version (listenTcp, etc)

But some people for some reason think, that an evented programming is actually the advantage of asynchronous I/O - probably because they have never used both models.

Yeah it's basically an unworkable model as soon as you have a client/server working through a conceptual set of shared/synced state. You end up having to break up a conceptually simple control flow into a messy explicit state machine on both ends... ick :)

Did you dig in far enough to explicitly enable the win32 back end or did you use the VisualD project? I'm asking because if the server is supposed to be command line only, the default libevent back end should work fine on Windows (for the VisualD project this would require removing the VibeWin32Driver version in the Compiler/General section).

VisualD project basically. I was originally just adding the relevant D files to my app directly (since I only really need to use it in "client" mode for now and want to keep the build simple for the time being) but ultimately I just added the VisualD project to my solution (and included a missing file or two) and then just linked the library and include vibe.vibe. Seems to be working fine other than the assert(false)'s that I hit when calling listenTcp, etc.

The win32 back end is currently developed in parallel to a larger project that needs it because it offers Windows event loop integration and a directory watcher. This is why it currently only has the features needed by that project. However, I wanted to get it completed for the next release (it would still be "beta" in that case regarding possible bugs and high-throughput performance). So if everything goes as desired, that would mean around the end of this month.

Great! Yeah it's actually pretty easy for me to "port" back and forth between my version and Vibe so when it's ready I'll happily drop the 3 or 4 files from my project that Vibe renders redundant :) Looking forward to using Vibe's much more polished HTTP/JSON setup vs. Phobos' minimal CURL/JSON stuff.

Re: Status of Win32 version (listenTcp, etc)

Oh forgot to mention, indeed command-line only is fine. Ultimately if this ever goes to "production" it'll probably end up on Linux actually, but for now it's convenient for me to develop it on Windows for a number of reasons.

I'll take a look into trying to use the libevent backend... any potentialy gotchas other than removing that other driver?

Re: Status of Win32 version (listenTcp, etc)

Am 17.12.2012 05:26, schrieb punkUser:

Oh forgot to mention, indeed command-line only is fine. Ultimately if this ever goes to "production"
it'll probably end up on Linux actually, but for now it's convenient for me to develop it on Windows
for a number of reasons.

I'll take a look into trying to use the libevent backend... any potentialy gotchas other than
removing that other driver?

If I'm not forgetting something important, no Windows messages and no directory watcher support
should be the only things. Oh, and file access is currently blocking, but that shouldn't really
matter for most things. I'll make that threaded shortly, though.

Re: Status of Win32 version (listenTcp, etc)

Great, the libevent version seems to work fine so far, thanks for the pointer!

One quick question... after using listenTcp is there a way to make it stop listening later? Other than that, everything has ported over easily and is running at least as well as before :)

Re: Status of Win32 version (listenTcp, etc)

Ah and now I've run into a slightly more serious problem... fibers don't like other fibers using "their" TcpConnections. That's going to be an issue, as there's several "broadcast"-like things that the server needs to do, and in fact not needing to do "safe" multithreaded code was part of the motivation for cooperative scheduling in the first place.

Is there a need for this restriction even when running in a purely single-threaded mode? Any easy way around it? I saw the broadcast example, but I'd rather not introduce explicit fiber message passing if I don't have to, since this didn't appear to be necessary on the old system.

I assume you're worried about certain yield points being at places where other use of the socket would cause issues, particularly stuff like closing the connection or similar. I suppose yielding when sending a particularly huge packet (if it does that) and then another fiber corrupting the data stream could be a concern as well, but in my old system there simply were no yields "in the middle" of sends... it would wait until it could atomically enqueue an entire packet before doing it.

Any suggestions? Am I forced to switch to message-passing and such even though I have no need for true multithreading/concurrency here?

Re: Status of Win32 version (listenTcp, etc)

On Tue, 18 Dec 2012 04:52:55 GMT, punkUser wrote:

Ah and now I've run into a slightly more serious problem... fibers don't like other fibers using "their" TcpConnections. That's going to be an issue, as there's several "broadcast"-like things that the server needs to do, and in fact not needing to do "safe" multithreaded code was part of the motivation for cooperative scheduling in the first place.

Is there a need for this restriction even when running in a purely single-threaded mode? Any easy way around it? I saw the broadcast example, but I'd rather not introduce explicit fiber message passing if I don't have to, since this didn't appear to be necessary on the old system.

I assume you're worried about certain yield points being at places where other use of the socket would cause issues, particularly stuff like closing the connection or similar. I suppose yielding when sending a particularly huge packet (if it does that) and then another fiber corrupting the data stream could be a concern as well, but in my old system there simply were no yields "in the middle" of sends... it would wait until it could atomically enqueue an entire packet before doing it.

Any suggestions? Am I forced to switch to message-passing and such even though I have no need for true multithreading/concurrency here?

OK, the main problem is, as you said, with yielding and the resulting possible fragmentation of the data stream. I see how it would be possible to add some kind of queue or a temporary lock that yields until all other fibers have finished writing, but there is still a large probability (for most applications) that high level code introduces race-conditions above the packet (or send()) granularity level. The other reason is that multi-threading is actually supported and the TCPConnection is typically only usable with one thread at a time (because the events only arrive in one thread).

But a simpler alternative to a message queue is to use a vibe.core.mutex.Mutex, which interacts gracefully with the event loop and then lock and aquire the connection only during a send:

auto mutex = new Mutex;
auto conn = connectTcp(...);
conn.release();
// ...
void sendPacket(...)
{
  auto lock = ScopedLock(mutex);
  conn.aquire();
  scope(exit) conn.release();
  conn.write(...);
}

Probably this usage pattern is useful in general. A template wrapper that does this could be added:

AutoLock!TcpConnection auto_lock_conn = AutoLock(connectTcp());

// locks and aquires
auto_lock_conn.write(...);

// or maybe
auto_lock_conn.performLocked((scope TcpConnection conn){ conn.write(...); });

// or (lock is scoped and non-copyable)
auto lock = auto_lock_conn.lock();
lock.write(...);

(But the name could be better...)

Btw. do you need to guarantee the same order of packets for all clients? If so, I think a message queue or a kind of mutex is needed anyway. Of course, it's possible to handle out-of-order packets on the receiver side, just wondering.

Re: Status of Win32 version (listenTcp, etc)

On Tue, 18 Dec 2012 03:21:15 GMT, punkUser wrote:

Great, the libevent version seems to work fine so far, thanks for the pointer!

One quick question... after using listenTcp is there a way to make it stop listening later? Other than that, everything has ported over easily and is running at least as well as before :)

I'm afraid I was too lazy to return some kind of handle from listenTcp that would make this possible ;) Will do as soon as possible.

(it just wasn't needed for the standard permanently running kind of server until now)

Re: Status of Win32 version (listenTcp, etc)

OK, the main problem is, as you said, with yielding and the resulting possible fragmentation of the data stream. I see how it would be possible to add some kind of queue or a temporary lock that yields until all other fibers have finished writing, but there is still a large probability (for most applications) that high level code introduces race-conditions above the packet (or send()) granularity level. The other reason is that multi-threading is actually supported and the TCPConnection is typically only usable with one thread at a time (because the events only arrive in one thread).

Right, I can certainly understand this. Like I said, I had basically just ensured that packet sends were "atomic" in my system, and thus whether a broadcast is done by one fiber or another was not really that relevant... it could just loop over all active connections and send the data.

Yes it's possible that things could happen somewhat "out of order", but in this case there's not a really well-defined order anyways since most/all of the broadcast-level events are triggered by clients themselves, so they already "race" to send data, etc.

But a simpler alternative to a message queue is to use a vibe.core.mutex.Mutex, which interacts gracefully with the event loop and then lock and aquire the connection only during a send:

So a vibe Mutex will yield the fiber when blocked? That's indeed an interesting solution.

Btw. do you need to guarantee the same order of packets for all clients? If so, I think a message queue or a kind of mutex is needed anyway. Of course, it's possible to handle out-of-order packets on the receiver side, just wondering.

Yeah as I mentioned I don't really have this constraint, but I'm starting to warm up to the notion of just storing a short packet queue for each client. If I use a "Signal" like in the broadcast example, I'm assuming I lose a lot of the niceness of blocking "deep" within TcpConnection routines (send/receive) though, right? i.e. because I need to be able to pop all the way back up to the top level and handle something unrelated (i.e. broadcast), and then find out how to go back down to where I was? Seems to negate a lot of the Fibering model if I'm forced to do it that way though. I think I'd rather it just work that if the fiber is blocked on "something else" (send/receive say) that it stays blocked, and only when it finishes all that stuff will it get back to the message queue.

I guess I'm not totally clear how Signal's interact with other events, including ones internal to Vibe. Is it basically a "wait on multiple objects" sort of scenario? If so, will the Vibe send/receive routines wake up, check that they still are blocked and yield again if the event being emitted is not relevant to what the Fiber is currently doing?

I might try the Mutex thing for now... seems like it should be a fairly good solution for me. A poorly-behaved TcpConnection could then of course block a lot of stuff though, so perhaps I need to rethink the design slightly.

I'm afraid I was too lazy to return some kind of handle from listenTcp that would make this possible ;) Will do as soon as possible.

No issues, I can live without it in the short term as well :) Was just curious if I had missed some bit of API.

Thanks for all the information! Getting pretty close to switching the mainline over to the vibe version :)

Pages: 1 2 3