Boost logo

Boost Users :

Subject: Re: [Boost-users] Does anybody interested in active object
From: Dean Michael Berris (mikhailberis_at_[hidden])
Date: 2010-11-08 04:45:39


On Mon, Nov 8, 2010 at 4:53 PM, Marat Abrarov <abrarov_at_[hidden]> wrote:
> To Dean Michael Berris:
>
> Thank you for your patience and detailed answers.
>

No worries. :)

>> Nope, sorry, s11n_example::connection is not an active object. What it actually is, is an execution
>> context -- or sometimes people call it a continuation, a generator, or a state machine. Because you're
>> using the execution context relevant with a particular connection, it doesn't imply that the
>> operations are performed on a different thread.
>
> Ok. May be I'm wrong trying to name it "active object".
> "Continuation", "state machine", "execution context" - this is very close to what I had in mind.
> Therefore, I conclude that we understand each other (despite some language barriers with my hand).
> I thought all of "Continuation/state machine/execution context" was related to the pattern of "active object", hmm...
>

Nope, continuation, state machine, and execution context are
independent of the active object pattern. There's a PDF somewhere of
the web of what the active object pattern is supposed to provide and
"look like". It might be good to look into the paper by Dr. Schmidt
who introduced the concept a while back:

  http://www.cs.wustl.edu/~schmidt/PDF/Act-Obj.pdf

>
>> If you have unlimited number of cores and no limits on the number of threads you can spawn for each
>> active object you create, then yes.
>
> I think the main feature of "Continuation/state machine/execution context" is not saving threads,
> but organizing flexible and comfortable way of communication between
> state machines (yes - it is tasks and queues, but wrapped in async method call with callback).

Well, even there what you really need is a means of encapsulating
tasks. If a task has dependencies and you follow the fork-join
parallelism model where you spawn additional tasks and pass around a
completion callback to do the "join", then that's really what you're
looking for. You can look at how TBB does it with its dynamic
partitioning to solve data-parallel problems using threads and tasks.
This only works though if you have minimal need for synchronization
across different tasks.

There are many different ways of doing it, and the active object
pattern really has nothing to do with massive parallelism.

> That is what I try to implement by means of Boost.Asio.
> It was chosen "historically" (started from network programming),
> but for the now times I see it is the best choice :)
>

Hold on there.

If you're doing data parallelism internal to an application, just
having tasks might not be the best choice. In a massively parallel
computation similar to what happens when you deal with graphical
systems or with SIMD parallelism, using just Asio+Boost.Thread will
not be sufficient (will even be suboptimal). This is why you really
ought to look at Boost.MPI, Boost.Interprocess, Boost.Thread, and
Boost.Asio for what their strengths are and choose which one you'll
need.

You choose the right tool for the job.

What's really lacking in Boost is well-performing implementations of
concurrent queue/hash/<insert data structure here> which we can use in
implementing our own producer/consumer queue and other parallel
partition-based algorithms. Asio just so happens to have a simple
io_service which does the dispatch and queuing internally -- (ab)using
that is not the best use of the library.

Also, there is already a proposal for C++0x to include a
std::thread_pool where you can throw tasks into. I'm not sure if
Boost.Thread will implement this or whether there are already other
libraries that do something similar, but that really is what you need.

>
>> Otherwise, you can stick with continuations, asynchronous completion handlers, and just plain data
>> parallelism.
>
> At the "samples" I develop (thanks to Boost.Asio examples - the are the first) the main goals were:
> 1) share execution context (thread pool) between different "state machines".

An execution context is not the thread pool. An execution context is
usually an object which has state encapsulated which is relevant to
the task. If you think about boost::bind(...) creating a function
object that has bound parameters, then the function object is said to
have its execution context encapsulated. This is how continuations
work, and how stackless programming works as well -- you rely on the
context that is available/local to the task/function when it is
invoked at some point in time.

> 2) (make possible to) divide execution contexts of different "state machines" and application layers
>   when it is needed (session and session_manager - not layers but are close to them).

You don't need Asio here.

> 3) develop a simple way of implementing async method call (for the "state machines") with required callback.
>   (with required usage of "custom memory allocation" which can make usage of async methods as cheap as possible)
>

There is a pattern called the accumulator -- which is technically a
function object that maintains its state across invocations. For
example, you might have an object that keeps track of the number of
times it's been called and every time its function operator overload
is called, it returns the previous count. Like this:

  struct accumulator {
    accumulator() : count(0u) {}
    unsigned int operator()() {
      return count++;
    }
    unsigned int count;
  }

In other programming languages that support closures, these would be
something you might call a closure. The point here is that all you
need to be able to perform asynchronous tasks and actions on different
threads is for you to bring the data required for that operation to
complete and package it up as a singular piece of computation as a
function object.

This is how tasks work, this is how Boost.Asio completion handlers are
invoked, and this is how task-based programming works.

If you discuss the fundamentals of these things instead of trying to
go to complex examples to bring the point across, maybe it would be
better, just a tip. ;)

Also, using more canonical terms would help a lot as well. :D

Oh, and please, don't top post.

HTH

-- 
Dean Michael Berris
deanberris.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net