Avoiding parent-to-child and child-to-parent pointers.

Programming, for all ages and all languages.
Post Reply
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Avoiding parent-to-child and child-to-parent pointers.

Post by AlfaOmega08 »

I consider myself quite a good C++ programmer, and I like to "follow the rules". But I can't solve this design problem.

It's all about my scheduler. Basically I have a Process class which contains a List<Thread *> member with pointers to it's threads.
The Process class contains PID, process path, the address space (PML4) and something more, while each thread has it's own TID, cpu context and a few other variables, AND a pointer to the parent Process.

Code: Select all

class Process
{
    ...
    List<Thread *> threads;
    ...
};

class Thread
{
    ...
    Process *parentProcess;
    ...
}
Everywhere I read on the web, this is highly discouraged: "Two classes needing each other would better be a single class.", and things like that. However I really need the ParentProcess pointer to read the AddressSpace field which is global to each process and not thread-specific. Having a copy of AddressSpace in each thread would be rather redundant and error-prone.

Even though my code would just work like this, I would like to remove this ugly thing from my code base. Any suggestions?
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by Combuster »

You'll have to show me where you got that mantra from because from my point of view it's a completely useless heuristic. It doesn't even show up on google as quoted.

What goes wrong is here that designed navigation is mixed up with designed separation of content. Pairs of information that requires exactly one of the opposite type is more efficiently stored as a whole because such a design enforces that they remain in pairs forever.

In this case there is a one-to-many relation between data, which makes the storage demand a separation of data types. That is what the class model demands.

On top of that is the navigation: if you have an instance of one class, you might or might not need to be able to find its relationships. One way of navigation is required - not storing the data means not storing any relation at all. Two ways may occasionally be necessary and it especially happens often when aggregations have some autonomous part: the parent makes the child do some work, and the child communicates back any interaction. Various languages have architected names for them: in java the implementations of the return path are called listeners. The entire collection of GUI classes is pervaded with them.

In data structures the bounds are even stronger: a graph for instance consists of a series of nodes and edges. While an edge can't exist without having a reference to two nodes, nodes can have any number of attached edges. which means that if you have any algorithm traversing the graph, you end up going from a node to an edge, and from an edge to a node, i.e. requiring both directions of navigation for any non-trivial algorithm to even work.


Short answer: what you're doing is perfectly fine.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
AlfaOmega08
Member
Member
Posts: 226
Joined: Wed Nov 07, 2007 12:15 pm
Location: Italy

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by AlfaOmega08 »

Combuster wrote:You'll have to show me where you got that mantra from because from my point of view it's a completely useless heuristic. It doesn't even show up on google as quoted.
I found it on StackOverflow. I can't find the exact question, and it wasn't an exact quote, but that was the meaning :D

Thanks again :)
Please, correct my English...
Motherboard: ASUS Rampage II Extreme
CPU: Core i7 950 @ 3.06 GHz OC at 3.6 GHz
RAM: 4 GB 1600 MHz DDR3
Video: nVidia GeForce 210 GTS... it sucks...
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by bluemoon »

stackoverflow is crap, I feel unlearning my programming skill just by reading the questions, and unlearn more when reading the answers.
User avatar
Ameise
Member
Member
Posts: 61
Joined: Fri Jul 16, 2010 7:46 am
Location: Chicago

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by Ameise »

I've heard of that 'rule' before. I write C++ professionally (game development)... and that rule just doesn't hold up in any industry, as far as I know.

There aren't many "rules" in regards to C++-style... everyone is unique. Some people, for instance, hate singletons, while other people use them. Use what works best for your situation. One of the beauties of C++ is that it gives you a lot of flexibility to write the code how you want, whereas other languages, like Java, don't.
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by bluemoon »

I only trust the rule of least surprise. When you use singleton, fine, just make it obvious and don't pretend to be a normal object :wink:
User avatar
NickJohnson
Member
Member
Posts: 1249
Joined: Tue Mar 24, 2009 8:11 pm
Location: Sunnyvale, California

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by NickJohnson »

All general rules are false.
User avatar
Ameise
Member
Member
Posts: 61
Joined: Fri Jul 16, 2010 7:46 am
Location: Chicago

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by Ameise »

NickJohnson wrote:All general rules are false.
As a general rule, I don't dereference null pointers.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by Solar »

Ameise wrote:
NickJohnson wrote:All general rules are false.
As a general rule, I don't dereference null pointers.
You don't? I do. :twisted:

If you have a circular dependency like that, at least think about it for a minute. I'm not sure "single class" is the general solution, though.

The very first thing I would do would be to make it a const & instead of a non-const pointer. You don't get away with an uninitialized pointer that way, and you make it clear that Thread has no business fiddling with Process internals.

Beyond that... what Ameise said. If you find an elegant solution for avoiding the circular dependency, fine. If you don't, I wouldn't worry too much -- C++ is about efficiency, not about adhering to specific design rules. Whether there is an elegant workaround or not depends on how your classes interact with each other. And it would have to be efficient as well, since you wouldn't want to add indirections with so frequenty-used classes as these. Actually, I'm not sure I would model these as classes in the first line.
Every good solution is obvious once you've found it.
User avatar
gravaera
Member
Member
Posts: 737
Joined: Tue Jun 02, 2009 4:35 pm
Location: Supporting the cause: Use \tabs to indent code. NOT \x20 spaces.

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by gravaera »

Yo:

I'd agree with Combuster, but if you want to avoid the possibility of null pointers being dereferenced:
  • If the parent process has been destroyed, it is expected that all of its child threads were destroyed along with it, so there is no chance of a stale pointer deref from the child thread's pointer to the parent.
  • If the child thread is destroyed, the linked list or array would have been updated when you removed the thread, such that the list no longer points to the child thread that was removed, or the array indicated in one way or another that the index is unoccupied; still no reasonable chance of a stale or NULL pointer deref.
--My say
gravaera
17:56 < sortie> Paging is called paging because you need to draw it on pages in your notebook to succeed at it.
OSwhatever
Member
Member
Posts: 595
Joined: Mon Jul 05, 2010 4:15 pm

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by OSwhatever »

Doing kernel programming you end up in chicken and egg and circular dependencies situations more than general user mode programming. My kernel is full of backwards references and they are indeed needed. Kernels are full of references back and forth in order to track the resources. You can avoid them but at what cost? Having backwards reference makes you quickly determine the parent. I rather have some ugly C++ programming rather than writing politically correct C++ programming if it helps me.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: Avoiding parent-to-child and child-to-parent pointers.

Post by gerryg400 »

Solar wrote:
Ameise wrote:
NickJohnson wrote:All general rules are false.
As a general rule, I don't dereference null pointers.
You don't? I do. :twisted:
Nearly, but not quite ;-) . The "->" does a dereference but the "&" cancels that out before any harm is done.
If a trainstation is where trains stop, what is a workstation ?
Post Reply