diff options
Diffstat (limited to 'TODO')
-rw-r--r-- | TODO | 138 |
1 files changed, 138 insertions, 0 deletions
@@ -0,0 +1,138 @@ +New, simpler design: + +There is an 'Engine' which is both Executor and Mainloop. It uses an +Epoll object to handle the polling. This epoll object does not do any +locking by itself. + +Contexts can be created; they are like jobqueues, except they also +allow you to add fd's and idles and timeouts. They can do that since +they have access to the engine. These are completely unlocked; if you +want to access a context from more than one thread, you must lock them +yourself. It is guaranteed that only one callback will be active for a +context at the same time. From within that callback it is then safe to +remove other callbacks etc. In general such a context can act pretty +much like one thread. + +A web server will consist of a listening context, which will create +other contexts as necessary and add the fd's to them with the +appropriate callback. Or maybe just call back with the new fd. I guess +there should be a generic listener object that will create its own +context and call back. Then an http module can just create a listener +and do whatever it wants in response. + +One possible problem. The thread that creates a context and adds the +fd not necessarily the one that will execute the first callback. Can +these interfere? Maybe the solution is just that the creating thread +should not do anything with the context after it adds the fd. A +better idea may be to just have a context_dispatch() function that you +must call after creating the context. Until this is called, nothing +the context is not active. + +Beginning of this new design is implemented and can be built with +build2.sh. + + + +Old design (referenced above) + +Highlevel design for a web server: + + - Executor + takes callbacks and executes them, possibly in parallell + or out of order. The callbacks are likely to be called in + a different thread than the one that queued them. + + Should support both push_back() and push_front(). Push_front() + is needed to do parallel requests with good latency. If + a request can be parallellized, the parallel tasks should + be put at the front of the queue. + + - EPoll + Simple class that wraps epoll()/poll(). Note: must support + oneshot polling and rearming. + + - JobQueue + Maintain a queue of jobs, uses executor to execute them + in order. Two jobs in the same JobQueue will never run + at the same time. + + - Mainloop + Uses executor, epoll. + - Takes filedescriptors and callbacks. calls + back when descriptor is readable/writable/etc. + - The callbacks are put on a job queue, which is passed in + - Each callback is a oneshot - ie., after calling, the + filedescriptor is not polled again until it is rearmed. + The mainloop will have a method to rearm filedescriptors. + This ensures that the mainloop can start a new poll() + whenever it wants without waiting for all the callbacks + to finish. + - Also takes timeouts that can be canceled. Timeouts also + need to be put on a queue. + + Sketch of implementation: + + polljob() + { + timeout = compute min_timeout (); + if (timeout > 0) + poll_armed_describtors(timeout); + call all timeouts (ie., put them on queues); + call all callbacks (ie., put them on queues); + schedule (polljob); + } + + - MainContext + + - The thing clients will deal with + + - Uses the main loop + + - Filedescriptors + maincontext is responsible for rearming the + descriptor after the client callback has been + called. + + - Timeouts + + - Idle handlers + + - Everything associated with a main context happens + serialized - ie., as if only one thread executed it. + + - This means a client structure doesn't need to be locked. + + - Has a get_executor() method so that clients can parallelize + if they want to. + + - Current thinking is that if we have main contexts, who + really needs a main loop? The only thing you could do + with it is to pass it to main contexts. + + OTOH that's true of several of the objects here. + see notes at top of maincontext.c + + - Worth noting that stuff that has to be passed in to + create a client object must be available to the + listener callback. But see http_server.c for an example + + - Err, the epoll in itself is not enough for maincontext, + since it needs to be shared between maincontexts. Ie., + who would call epoll_wait(). We do really need a main + loop that will call back. + + - Listener + Listens on a port. Calls back with a file descriptor when + someone connects. + + - Connection + initialized with a MainContext and a filedescriptor. + Creates events when something happens + + - Http: + Has a Connection + parses http, emits events such as + "get hostname pagename query" + "post etc etc etc" + + - ContentProvider |