Re: Passing generic data between thread
On Jun 21, 5:27 pm, ittium <itt...@gmail.com> wrote:
I want to pass data between two threads. Type of data can vary.
data
{
list l;
map m;
}
data
{
int i;
long l;
}
I can think of following ways to do it
1. write serialise routines so that between the thread, encoded void*
buffer is passed. But since thread will run in same address space,
serialization seems to me as overkill.
2. Pass a token (specifying the type) and data typecasted to void*.
Receiving thread can typecast the data to actual type based on the
token
3. Use boost:any and then receiver can find out type using RTTI.
It is not necessary to use boost any for this.
You can do this kind of thing by using commands
(GOF command pattern), a command having an
association with the queue in whose thread it will
be executed.
Continuing from the GOF pattern, "execute" is called
from the thread receiving the command. A clone of
the command is sent over the queue (pointer only), and
during the clone ownership of the argument of the command
is transferred from the envoked command to the cloned
command.
The envoked command sets the data using overloaded
operator()( argT ), then, depending on a storage policy,
on cloning the command, the ownership of the argument
is either transferred copied (for small objects).
Pre-allocated memory pools are used for memory of the
commands and their arguments (depending on storage pol).
Getting of memory in the pools are done by performing a binary
lookup to get the correct memory size, and returning of the
memory is done my storing a hidden pointer to the pool in
front of the memory.
Psuedo (very quick take):
class CmdExecutable
{
public:
//Called by executing thread...
virtual void execute() = 0;
};
class CmdProcessable : CmdExecutable
{
public:
virtual CmdProcessable* clone() const = 0;
};
class Cmd : CmdExecutable
{
public:
//<mngr> determines context of execution...
Cmd( CmdServer* server );
//If we have a queue, post myself over the queue
void process();
void operator()(); //Does the same as process
//I know clone has better/canonical implementations, but
// you get the idea
virtual Cmd* clone() const = 0;
private:
virtual void execute() = 0;
};
class CmdServer
{
public:
void process( const CmdProcessable& cmd )
{
mail( cmd.clone() );
}
// Implementation mails cmd over thread safe queue.
virtual void mail( CmdProcessable* cmd ) throw() = 0;
};
class CmdExecutor : public CmdServer
{
public:
void serviceCmdQueue() throw();
private:
//All v functions required by service...
};
void CmdExecutor::serviceCmdQueue() throw()
{
//Psuedo code...
CmdExecutable* cmd;
//This call should block until next cmd arrives on queue
unsigned size( retrieveNextCmdBlock( &cmd ) );
//Some error checking...
//Ensures deletion at end of this scope...
std::auto_ptr<CmdExecCmd> scopedCmd( cmd );
//Handles possible rendezvous with caller...
using namespace AviUtils;
ActionAtScopeEnd
handleRendez( mkAction( HandlePossibleRendezvous( *cmd ) ) );
valueUsed( handleRendez );
//Executes the command, passing associated arguments
// along with function (not shown for brevity)
cmd->execute();
}
Perhaps you get the idea, but I've left out lots
of gory detail.
Regards,
Werner