On 2013-12-06 1:06 PM, Sergei Nosov wrote:

Hi!

I have 2 general questions on the implementation. Maybe someone could give brief answers or some links with explanation?

  1. vibe.d claims to have asynchronous I/O via fibers. As I understand it - this means the flow looks something like this. When we're handling a request we come to a certain point, where we need to e.g. query a record from DB. We issue an asynchronous request and call smth like yield, not to waste CPU time. Someone wakes us later, we check for the status of the request, and proceed if it's ready, or yield again otherwise.

So, it brings the question - in that case - who is responsible for calling yield? I assume if I'm not calling it myself, it should be called by the vibe.d functions. So, if I want to read from file - I shouldn't use readText, but should use some vibe.d yield-aware alternative. Is that the case?

  1. Suppose, I have a class instance with state - e.g. a cached value of something. In each request I check if the value should be updated, possibly update it and proceed using this value. How I should make it work in vibe.d? If I create a class instance in shared static this(), then as I understand, the instance is shared among all of the threads, so if I use the cached value without synchronization - it's a race. Is that so? How can I avoid it?

1)
ctx.core.yieldForEvent is called automatically in
vibe/core/drivers/libevent2_tcp.d at a lot of locations after reading or
writing data to or from buffers.

The fiber is resumed when ctx.core.resumeTask is called after a callback
is triggered from libevent2 here:

buffereventsetcb(bufevent, &onSocketRead, &onSocketWrite,
&onSocketEvent, client_ctx);

If you need to run routines that take a lot of CPU cycles, you can call
yield() every now and then to make sure other requests aren't left out
while this operation runs.

2)

You should place variables shared between fibers outside the scope of
shared static this()

Fibers don't race with each other, they are called sequentially in an
event loop as they are paused and resumed. Only threads are exposed to
data races, but by default, vibe.d runs on one thread only. Regardless,
D's variables are all thread-local by default as well. You can use
gshared storage specifier if you want to share globally, this is the
only possibility of there being a data race. It's recommended to use D's
synchronized specifier to lock global methods in a mutex if you need to
consult a
gshared object.

Read more here: http://dlang.org/migrate-to-shared.html