require advice in this design issue specific to c++

A

abir

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.
 
N

news.chris.theis

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
 
A

abir

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.
 
N

news.chris.theis

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top