procedure programming - brief

Mar 12, 2014 at 7:50 AM
Edited Mar 12, 2014 at 7:53 AM
nothing in a computer system is unexpected, we are always able to get signal when something happened. but currently most of the components in the software system are in 'poll' mode. such as lock, sync IO, etc. which is a kind of disaster. the software system will use up to 50% of the processor resource to switch between threads, if the application has hundreds of threads, but waiting for the IO to finish or lock to release. and if we are using apache mode [one thread per request] for any online service, the peak QPS is limited as the thread_count * 1 / IO_delay.
so we should try to use async and lock free solutions.
but async is not as friendly as sync, you need to take care of lots of stuff, lock free data structures are even more difficult. there are some tries existing, say, using yield return, IAsyncResult, async / await. but these solutions do not provide a whole solution to handle both async and lock free. this is the reason for the procedure programming i have worked on.

the basic idea is to use lambda expressions to store internal data, while each lambda expression is a part of whole procedure with processor work, or called step. at the end of each step, the procedure can drop into a pending status by wait an async IO to finish, wait for a signal to be set, wait for a lock to release, etc. after the waiting signal has been triggered, the procedure can continually work in the next step.

you will need it if you are in the following status,
  1. cannot handle lock well, or stuck in a deadlock
  2. hate to write async code, since it's not pretty and hard to write / debug
  3. hit by a performance issue
  4. need to have several extra threads to handle some regular jobs
  5. though .net 4.5 support await, but you need to write everything await to make them work e2e, you cannot control where to sync, where to async
briefly you can write async code like this,
dim ec as event_comb = nothing
return new event_comb(
                    function() as boolean
                        return waitfor(an_event_comb_lock) andalso goto_next()
                    end function,
                    function() as boolean
                        ec = some_other_async_io_operation()
                        return waitfor(ec, timeout_ms) andalso goto_next()
                    end function,
                    function() as boolean
                        return ec.end_result() andalso goto_end()
                    end function)
and start the event_comb with
then you will not need to warry about any async io operation, and more.

currently the procedure have supported
  1. event_comb w/ timeout control
  2. extensions for some async io classes, such as stream, httplistener, to help create an event_comb
  3. waitfor another event_comb, or a set of event_combs
  4. waitfor a sync io operation if it's not supported <say File.Move>
  5. waitfor a certain time, surely not block any thread
  6. event_comb_lock, which is a cross-thread lock, make everything else lock-free
  7. waitfor a singleentry
  8. control the step based on several goto commands
the source code is under