[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

require advice in this design issue specific to c++

abir

10/17/2008 7:23:00 AM

I am working on a project, where i am dealing with a series of
geometric
algorithms which will works in sequence to transform the input data
to the result using a few steps.
Input data is a sequence of points supplied by user and stored in a
deque.
struct point{
int x;
int y;
};
The algorithms take the input & one or more intermediate results to
produce
next result.
I am storing all of the results & input in a Context class, like
struct context{
std::deque<point> input;///input by user.
std::vector<sprite> sprites;///generated by create_sprite, uses
input
std::vector<actor> actors;///generated by create_actor uses input &
sprites.
std::vector<logo> logo_elements;///generated by create_logo, uses
input & actors
std::vector<character> characters;///by create_character ,uses
sprites,actors & logo. these are final result
};
as all of the algorithm needs some sequence from the context class,
and creates some
more sequence in the context class, and most of the elements like
sprite ,actor etc
have the member method to get pointer to other sequences, so at
present i am storing
context pointer to all algorithms (8-10 in number, i dnot have problem
to store them)
& all such elements (1000's in number)

eg:
struct sprite{
context* ctx_:
std::pair<int,int> points_;
std::pair<std::deque<point>::iterator> get_points(){
return std::make_pair(ctx_->input.begin()+points_.first,
ctx_->input.begin()+points_.second);
}
};
for actor :
struct actor{
context* ctx_;
std::pair<int,int> points_;
std::pair<int,int> sprites_;

std::pair<std::deque<point>::iterator> get_points(){
return std::make_pair(ctx_->input.begin()+points_.first,
ctx_->input.begin()+points_.second);
}
std::pair<std::vector<sprite>::iterator> get_actors(){
return std::make_pair(ctx_->sprites.begin()+points_.first,
ctx_->sprites.begin()+points_.second);
}
};
(NOTE: i am not directly storing pointers to the sequences, rather
storing positional
indices, as pointer gets invalidated when i put more data in the input
& compute some intermediate results. Also i am not storing
vector<sprite> in actor
class itself as, sprites are pointed by many other classes than actors
alone,
as with points).

Now I have 3 options to deal with the context class,
1) store context pointer where it is needed as shown.
2) use global context variable/function / singleton etc
(i am not using multi threaded env at present, but in future may
need
thread specific context instead of global if needed). Also as i
don't use
any other global variable, have no problem with initialization
order.
eg:
extern context* g_ctx;///global or TLS data depending on threading
env.
struct sprite{
std::pair<int,int> points_;
std::pair<std::deque<point>::iterator> get_points(){
return std::make_pair(g_ctx->input.begin()+points_.first,
g_ctx->input.begin()+points_.second);
}
};
3) I can pass the context parameter to everywhere when it is needed
rather than storing it.
(like posix strtok )
eg:
struct sprite{
std::pair<int,int> points_;
std::pair<std::deque<point>::iterator> get_points(context& ctx){
return std::make_pair(ctx.input.begin()+points_.first,
ctx.input.begin()+points_.second);
}
};
My algorithm need to call get_points etc from very inner loops.
at present i am using method 1)
method 1) & 3) looks ok to me, where method 1 stores lots of context
pointer
in each of actor , sprite & other elements but has a cleaner api.
where method 3) doesn't do that but have a clumsy api.
not sure about method 2) as i never used global/extern/singleton etc
previously
in c++ projects. So not sure about its performance, risk etc esp if
used with
thread specific ptr.

I am little confused over which method should be used and follows best
design practice
at the same time.
Any advice on which method is in general favorable, and should be used
is highly appreciated.

Thanks to all in advance.
3 Answers

news.chris.theis

10/17/2008 8:41:00 AM

0

On Oct 17, 9:22 am, abir <abirba...@gmail.com> wrote:
> I am working on a project, where i am dealing with a series of
> geometric
> algorithms which will works in sequence to transform the input data
> to the result using a few steps.
[SNIP]
> Now I have 3 options to deal with the context class,
> 1) store context pointer where it is needed as shown.
> 2) use global context variable/function / singleton etc
>    (i am not using multi threaded env at present, but in future may
> need
>     thread specific context instead of global if needed). Also as i
> don't use
>     any other global variable, have no problem with initialization
> order.
> eg:
> extern context* g_ctx;///global or TLS data depending on threading
> env.
> struct sprite{
>   std::pair<int,int> points_;
>   std::pair<std::deque<point>::iterator> get_points(){
>     return std::make_pair(g_ctx->input.begin()+points_.first,
>        g_ctx->input.begin()+points_.second);
>   }};
>
> 3) I can pass the context parameter to everywhere when it is needed
> rather than storing it.
>    (like posix strtok )
>    eg:
> struct sprite{
>   std::pair<int,int> points_;
>   std::pair<std::deque<point>::iterator> get_points(context& ctx){
>     return std::make_pair(ctx.input.begin()+points_.first,
>        ctx.input.begin()+points_.second);
>   }};
>
> My algorithm need to call get_points etc from very inner loops.
> at present i am using method 1)
> method 1) & 3) looks ok to me, where method 1 stores lots of context
> pointer
> in each of actor , sprite & other elements but has a cleaner api.
> where method 3) doesn't do that but have a clumsy api.
> not sure about method 2) as i never used global/extern/singleton etc
> previously
> in c++ projects. So not sure about its performance, risk etc esp if
> used with
> thread specific ptr.
>
> I am little confused over which method should be used and follows best
> design practice
> at the same time.
> Any advice on which method is in general favorable, and should be used
> is highly appreciated.
>
> Thanks to all in advance.

Hi Abir,

to my mind option 1.) looks fine for your current environment as it
seems logical to have a pointer to the context object stored in the
sprites/actors as they have to communicate with their environment.
Passing the context object every time you need it would on one hand
clobber your code and on the other hand it might (depending on the
case) impose some runtime penalty. So for the single threaded
environment I'd go with option 1.

If you're really considering multi-threaded environments then things
become more complicated and you might consider a thread-safe
singleton. Even for now you could use a singleton although it's not
really necessary. I'd recommend to look at the book "Modern Design C+
+" by A. Alexandrescu where you can find an extensive description of
the singleton design pitfalls and example code that might be helpful.
In any case you should think whether threads are really necessary
because it will increase the complexity of your design considerably.

Cheers
Chris


abir

10/17/2008 9:34:00 AM

0

On Oct 17, 1:40 pm, news.chris.th...@gmail.com wrote:
> On Oct 17, 9:22 am, abir <abirba...@gmail.com> wrote:
>
>
>
> > I am working on a project, where i am dealing with a series of
> > geometric
> > algorithms which will works in sequence to transform the input data
> > to the result using a few steps.
> [SNIP]
> > Now I have 3 options to deal with the context class,
> > 1) store context pointer where it is needed as shown.
> > 2) use global context variable/function / singleton etc
> > (i am not using multi threaded env at present, but in future may
> > need
> > thread specific context instead of global if needed). Also as i
> > don't use
> > any other global variable, have no problem with initialization
> > order.
> > eg:
> > extern context* g_ctx;///global or TLS data depending on threading
> > env.
> > struct sprite{
> > std::pair<int,int> points_;
> > std::pair<std::deque<point>::iterator> get_points(){
> > return std::make_pair(g_ctx->input.begin()+points_.first,
> > g_ctx->input.begin()+points_.second);
> > }};
>
> > 3) I can pass the context parameter to everywhere when it is needed
> > rather than storing it.
> > (like posix strtok )
> > eg:
> > struct sprite{
> > std::pair<int,int> points_;
> > std::pair<std::deque<point>::iterator> get_points(context& ctx){
> > return std::make_pair(ctx.input.begin()+points_.first,
> > ctx.input.begin()+points_.second);
> > }};
>
> > My algorithm need to call get_points etc from very inner loops.
> > at present i am using method 1)
> > method 1) & 3) looks ok to me, where method 1 stores lots of context
> > pointer
> > in each of actor , sprite & other elements but has a cleaner api.
> > where method 3) doesn't do that but have a clumsy api.
> > not sure about method 2) as i never used global/extern/singleton etc
> > previously
> > in c++ projects. So not sure about its performance, risk etc esp if
> > used with
> > thread specific ptr.
>
> > I am little confused over which method should be used and follows best
> > design practice
> > at the same time.
> > Any advice on which method is in general favorable, and should be used
> > is highly appreciated.
>
> > Thanks to all in advance.
>
> Hi Abir,
>
> to my mind option 1.) looks fine for your current environment as it
> seems logical to have a pointer to the context object stored in the
> sprites/actors as they have to communicate with their environment.
> Passing the context object every time you need it would on one hand
> clobber your code and on the other hand it might (depending on the
> case) impose some runtime penalty. So for the single threaded
> environment I'd go with option 1.
>
Thanks for answering. I really don't need a multi threaded env in a
sense that
no mutex or locking is needed. However there can be many users & so
per user(per thread)
context can be there. Though at present i am forking a new process
for each user, rather than creating a new thread. But as i have no
global at present, i can do the other option equally well.
I "think" for both option 1) & option 3) a per thread context has no
problem.
While for option 2) a TLS is needed instead of global.
> If you're really considering multi-threaded environments then things
> become more complicated and you might consider a thread-safe
> singleton. Even for now you could use a singleton although it's not
> really necessary. I'd recommend to look at the book "Modern Design C+
> +" by A. Alexandrescu where you can find an extensive description of
> the singleton design pitfalls and example code that might be helpful.
> In any case you should think whether threads are really necessary
> because it will increase the complexity of your design considerably.
>
I am fearing that, and really trying to avoid global variables mostly
because i am not sure of performance of global in inner loop (also
some platform
doesn't support global Symbian? )
Will go through the chapter again.
So i assume i am going in right direction.
Thanks again for reply.
> Cheers
> Chris

news.chris.theis

10/17/2008 12:50:00 PM

0

On Oct 17, 11:34 am, abir <abirba...@gmail.com> wrote:
[SNIP]

> Thanks for answering. I really don't need a multi threaded env in a
> sense that
> no mutex or locking is needed.  However there can be many users & so
> per user(per thread)
> context can be there.  Though at present i am forking a new process
> for each user, rather than creating a new thread. But as i have no
> global at present, i can do the other option equally well.
> I "think" for both option 1) & option 3) a per thread context has no
> problem.
> I am fearing that, and really trying to avoid global variables mostly
> because i am not sure of performance of global in inner loop (also
> some platform doesn't support global Symbian? )

I'm not sure up to which point a global variable might become a
runtime bottleneck. That would have to be checked for your case &
compiler. However, I'd stay away from global variables as much as
possible and go with singletons as you have much better control.

As you say that you will not tread into the depths of mutexes & locks,
I would say that your first option should do the trick just fine.

Cheers
Chris