jacksonh / manos

Manos is an easy to use, easy to test, high performance web application framework that stays out of your way and makes your life ridiculously simple.
Other
454 stars 61 forks source link

Understanding Manos' Threading Model #112

Closed toptensoftware closed 13 years ago

toptensoftware commented 13 years ago

This is not an issue, but me trying to understand Manos' threading model - what is and isn't supported.

I've seen various discussions about Manos' non-blocking event driven IO model, using the ThreadPool for long running operations, comments about Manos being something quite different from ASP.NET and designed to solve different problems etc... but I've not seen a good discussion about what is and isn't allowed from a threading perspective.

I guess my main question is this: suppose I use the thread pool to run a blocking operation (eg, the typical case of creating a controller, doing some DB work, and rendering a view) do I need to write the http response from Manos' context loop thread or can I send it from the thread pool thread?

Or, perhaps I can write the response from the thread pool thread, but need to end the response from the context loop thread?

Or, perhaps writing from another thread is allowed, so long as I only write from one thread at a time?

Or, perhaps nothing is allowed from other threads?

Threading is an area where you can't just try it and see what works so any information to clarify Manos' threading capabilities would be of great help.

(Oh, and being able to at least write the response from one other thread would be awesome).

ghost commented 13 years ago

It's quite simple: any and all interaction with context is allowed only from withing the context thread - except for one operation, which is IAsyncWatcher.Send. Specifically this also means that all interaction with http requests and responses in Manos is allowed only from within the context thread.

Writing to the response from another thread can be accomplished by adding a delegate that writes to the response to the Boundary associated with the Context (only one, currently, but that's subject to change).

toptensoftware commented 13 years ago

Hi Myeisha,

Thanks for your quick reply. I'm a little surprised to hear that not even the request object can be read from another thread... I'd already taken a pretty close look at that and thought it would be ok. Let me describe what I'm trying to achieve and perhaps you can offer some insight/explanation.

Our rationale for looking into Manos is not so much because we need an event driven architecture. Although that is a part of it we're also simply after a framework that we have complete control over, is simple, lightweight and will run well on both Windows (for development) and Linux (for production). Manos fits that bill nicely.

We have an existing project written in ASP.NET MVC that we'd like to port so I've built a lightweight MVC framework that is similar to ASP.NET MVC but built on top of Manos. Most of the requests to this app are typical request -> blocking db queries -> response view. Porting all that DB logic to an async model is not really feasible.

So, in our MVC framework I've added an attribute [UseThreadPool] that moves the processing of specific controller actions to a threadpool work item. Pretty much the whole request is processed on that thread pool thread - including binding uri, form and querystring data to action parameters and models, instantiating the controller, running the action and rendering the response view.

Rendering the response view I can probably resolve by shuffling the write operations back onto the context thread, but I don't understand the reason not being able to read request data from the other thread. Does Manos continue to manipulate the request object after the route handler is called but before the response is ended? I thought that during this period the thread pool thread would be the only thread using this object and reading the request data would be fine.

Please don't take this the wrong way... I'm not arguing the point, I just want to understand what I need to do to get this working reliably. I realise that I'm probably bending Manos in a way it wasn't intended but it's seems so close.

ghost commented 13 years ago

I'm sorry for not answering reasonably clear. Of course you are right, data that has already been read from the stream and stored in request/response objects can be used from another thread. Care should be taken that no more than one thread accesses these objects though, as usually.

The forbidden actions are only those that need the context for interaction with the outside world, which would be reading from/writing to the network, reading/writing files, making http requests and reading their results, things like that. If an operation does not touch the context, it can move freely among threads.

The scenario you described should work with manos pretty much out of the box. The pipeline is still a bit daft though, so using it might break your application. I advise against the pipeline anyway, since it's currently rather useless.

toptensoftware commented 13 years ago

Thanks for the clarification that makes sense and is closer to how I imagined it would work. Looks like I just need to resolve the response writing and it should be good to go. I'm not using the pipeline stuff at all.

Thanks again for your help... much appreciated.