Jump to content

  • Log In with Google      Sign In   
  • Create Account


Trienco

Member Since 22 Aug 2001
Offline Last Active Yesterday, 09:56 PM

#5090523 multi-thread

Posted by Trienco on 30 August 2013 - 10:57 PM

I was somewhat hoping the old "let's put each module in a separate thread"-approach has died out a while ago, when developers realized that having all these threads constantly compete for the same resources is a messy nightmare of synchronization and race condition bugs. Unless you make sure that all the modules working in parallel only read the same data. Alternatives usually involve either a lot of copying or a lot of locking. Don't be surprised if the overhead ends up making the whole thing pointless.

 

A first step is to simply use concepts like parallel_for to split up one huge chunk of work to be processed in parallel (note: make sure each element can be processed independently of others). After that, look into task based parallelism. Intel's TBB library and especially its documentation might be a good place to start.




#5090328 using detours 3.0 crash

Posted by Trienco on 30 August 2013 - 02:32 AM

Isn't GetProcAddress a function? Why are you handling it as a null terminated string? The bigger surprise is that it's not already crashing the first time, but you're probably lucky to have a zero on the stack nearby. Output pointers as %p, not as string.




#5089426 passing std::shared_ptr to a function?

Posted by Trienco on 27 August 2013 - 01:54 AM

And yet the fact that operator-> is automatically called recursively until it returns an actual pointer type is occasionally used to implement special behavior or convenient helper functions by using wrapper objects that implement it. It's often the easiest way to keep the calling code clean and blissfully ignorant of implementation details. Try implementing a special proxy on top of a basic proxy to some generic object without exploiting operator->.

 

Basically, the question is: what happened to old-fashioned ways to mark members like 'mMember' or 'member_' that don't have the potential for obscure side effects?

 

There is no ambiguity for functions either, as a function is either a member, global or called through some other object. Global functions should be in a namespace and "using namespace everything" is often preferring laziness over clear code. So suddenly foo() is obviously a member function, as otherwise it would be something like std::foo() or ::foo().




#5089417 Convert C function args to CPP function args

Posted by Trienco on 27 August 2013 - 01:20 AM

Fixing all the existing code might be a bit tedious, but at least all new code should be const correct right away. If the function will not modify the string behind the pointer, it should clearly say so by using const. The most critical reason is that otherwise the function will be incompatible with C++ code that uses std::string (.c_str() returns a const
char*). Personal highlight: a coworker actually adding a comment that his function will not modify the string instead of just making the darn thing const.

 

If the point is to C++ify the code, I'd go one step further and use std::string as much as possible (functions then take 'const string&', rather than 'const char*').




#5084310 Duplicated Code

Posted by Trienco on 08 August 2013 - 10:26 PM

Ask yourself this: if instead of describing forms (which are basically just 90° steps of rotation) you would describe a free rotation, would you go and create 360 bools all called rotated1Degree, rotated2Degree, ...? What if you need half or quarter degree steps? Because that's essentially what you are doing right now, except it hasn't yet reached the point of becoming obviously ridiculous and unmaintainable.

 

In terms of getting the project done: it works, move on.

In terms of practice or better code: consider some of the cleaner approaches mentioned above.

 

How are you doing all the other stuff like drawing? Is there a lot if if-else to pick the right shape? Wouldn't it be easier if the form was a number that also just indexes into an array with the correct shape? Are you checking for consistency (always one and exactly one of them being true)? Basically when you say "mutually exclusive" that should also mean "not stored as multiple bools".




#5078370 Function addresses are not fixed relative to each other?

Posted by Trienco on 16 July 2013 - 10:13 PM

When you cast your function pointers to integers, I'd always preclude that with a static-assertion testing that the size of your function pointer type is smaller or equal to the size of your int type.

 

Of course, if I really have to use printf to output any kind of pointer, I'd just use %p in the first place...




#5078047 Problem with strings

Posted by Trienco on 15 July 2013 - 10:27 PM

Which is why a / should be used as a path separator whenever possible (yes, even on Windows). There are extremely few cases where it won't work.




#5077017 Organizing Source Files

Posted by Trienco on 11 July 2013 - 10:08 PM

I'd generally prefer the ProjectDir (which also seems to be the "default" as in "what your path is relative to if you don't specify anything). Nothing more frustrating than adding a project as a dependency to a different solution and having all your paths fall apart.




#5074338 Header Files

Posted by Trienco on 30 June 2013 - 10:25 PM

Ah, surprisingly I am often amazed that even many "professional" programmers have no idea how this works in detail. There will be a big step back to explain the two phases of making an executable.

 

Compiling: every .c/.cpp/.cc (whatever your source files are called) is compiled in complete isolation. It knows absolutely nothing about the content of any other source file. This will usually create one compiled object file for every source file.

 

Linking: this pieces together all the object files into one big executable binary. This is also the step where every function that is being called must exist in one (and exactly one) object file (or one of the linked libraries). Same goes for global or static member variables.

 

Another important distinction is "declaration" vs. "definition". A header should usually contain only declarations (or inline code). Declarations say "this thing exists somewhere", while a definition says "this right here IS the thing". For global variables, "extern" is used to tell a declaration from a definition. For functions this difference is having or not having a function body.

 

 

So headers are a) never compiled on their own and b) are completely irrelevant for linking. They are needed to be able to compile source files that are using or referencing stuff that is "somewhere else". However, these are only declarations. Also, linker errors will never ever be fixed by touching #includes (except maybe by removing them if your compiler is seriously trying to link stuff that is never actually used).

 

There is also the issue of circular includes. If your includes ever start going around in circles, this is a bug and no, inclusion guards have nothing to do with it and won't fix that. The only solution is to not them and use forward declarations to break them up (using forward declarations as much as possible in header files is generally preferable anyway, especially when it comes to compile times). This is also one big reason why not to spam includes all over the place in header files, just in case they _might_ be needed or out of sheer convenience (my favorite quote from a coworker "but this is way easier, so everyone including this header automatically gets all the other stuff".. uhm, yes, including all the stuff they don't need, that might result in conflicts and will blow up compile times by a few multitudes).

 

 

So random guesses:

-your header includes something, but not RakNetTypes.h

-your header is trying to include itself

-the header isn't found and you are not looking at the error messages starting at the top

-there is a typo in the identifier




#5073121 Static Initialization and Ctors

Posted by Trienco on 26 June 2013 - 09:38 PM

If you really and absolutely must have the map as a global, wrap it in a function so it is guaranteed to get initialized on the first call. Though "is there really no better way" should always be asked before turning to Singletons. But usually having to do this for every map should be deterrent enough.

 

map<unsigned, SceneElement*>& someMap()
{
    static map<...> myMap;
    return myMap;
}



#5072390 Bill-boarding oriented rectangle

Posted by Trienco on 23 June 2013 - 10:26 PM

Building the objects transformation matrix yourself sounds like the easiest approach, except that the two vectors to build the rotation part from are p2-p1 and (to make it face the camera) camera.position - p1 (or any other point on the line).

 

From there you just get the third vector with a cross product and after that use another cross product between the first and third vector to "fix" the second one (to be orthogonal). Normalize all vectors and you should be done. In your matrix, the first vector is the x-axis, the third one is the y-axis and the second is z. That choice is arbitrary and only depends on how your rectangle is modeled (I assume x being along the length, y being the width and z being the normal vector facing the camera).

 

There is no manual scaling going on unless what you mean is that is has to scale itself to cancel out the scaling you get from perspective projection.

 

When you create the geometry, do _not_ center it around the origin or you're just making it pointlessly complicated to move it into position. Just use (0,width,0), (0,-width,0), (length,width,0) and ((length,-width,0).

 

That approach has worked perfectly fine to have a ton of laser beams flying around. At least it's how I remember it, since the whole project seems to have disappeared.




#5066055 Strange problem with delete with VS 2012.

Posted by Trienco on 29 May 2013 - 11:32 PM

In case "pointer" is a member of the object, I would be extremely worried if the bug disappears, just because it's set to null after delete. In fact, I would strongly advice _against_ setting member pointers to null in your destructor, exactly because it can hide more severe bugs. Doing so should have absolutely zero effect on program execution, unless something else is wrong (like deleting the actual object twice). In that case, reliably crashing is the best that can happen, as it clearly shows that something is wrong (instead of causing weird and inexplicable behavior down the road).




#5062193 c++ include define DIR

Posted by Trienco on 15 May 2013 - 10:03 PM

As mentioned above, there's a whole bunch of methods that are all better than abusing the preprocessor for this.

 

a) If stuff is versioned, why not use a version control system instead of folder names?

b) Failing that, the -I option exists for exactly that kind of thing (ie. it belongs in your project settings or Makefile, not the actual source code)

c) Use a symlink that points to whatever version you want to use (yes, Windows finally has them too)




#5062192 My ever-evolving coding style

Posted by Trienco on 15 May 2013 - 09:51 PM

Whenever writing a million getters and setters gets annoying, I usually ask myself two things:

 

a) if I just go and write trivial set/get methods for everything, why not just stop pretending and make it public?

 

b) why not be lazy and wrap it in a template that handles it?

 

class ...

{

...

   Property<int> stuff;

};

 

int value = obj.stuff();

obj.stuff(5);

obj.stuff( obj.stuff() + 5 );

 

Not calling it get and set allows to use the template for all trivial cases and do custom implementations where needed without requiring a different syntax.

 

Still, if a class has a dozen members and trivial accessors for all of them, encapsulation probably just went out the window. So it's more of a convenient way to remain consistent.




#5061418 tictac toe marks

Posted by Trienco on 12 May 2013 - 10:09 PM

Generally by giving them names and making them constants, but that only applies to numbers that _must_ be defined in the program and won't change at runtime. The resolution or window size for a PC application should not be a magic number or a constant, because you don't know what hardware people are using.

 

In your case: by learning how to use structs, arrays, loops and functions.

 

Just doing a find/replace and creating thousands of constants like "block1TopLeftX" and "block3BottomRightY" might get rid of magic numbers, but is also insanely silly, because a sane person would never want to hard code everything for every single block in every single level of a game like Breakout (which will be thousands or even a lot more). Always tell yourself "there will probably be a bug in this code, I don't want to fix the same bug in 10000 copies of this". In fact, writing the same snippet more than twice (at most) is usually a bad sign.

 

Force yourself to keep things flexible. Plan for change, write code that will work no matter if your game board is 3x3, 5x5 or any other size (somewhat limited by screen size) and don't assume you will always need 3-in-a-row. Make board and required row size a variable and don't use magic numbers or constants. Remove the option to just hard code everything and force yourself to think in algorithms instead of a huge list of if-elses.






PARTNERS