Jump to content

  • Log In with Google      Sign In   
  • Create Account

Codarki

Member Since 17 Feb 2004
Offline Last Active Sep 13 2013 07:22 PM

#4874694 Float to bits

Posted by Codarki on 20 October 2011 - 08:14 AM

Use fixed-point math for that. Then you have floating point fraction as a nice integer.

// 8 bits.
char fraction = static_cast<char>(static_cast<size_t>(float_value * 256.0f) & 0x0ff);



#4870043 Multiple classes in the same .h and .cpp files

Posted by Codarki on 07 October 2011 - 03:32 AM


There may be times when I'll put several related classes in one header for cohesive browsing, but break implementations out into multiple files.

I'd advise to put headers into their own files, and share the implementation in single cpp if you must.

This was my disagreement.


Low granularity on headers will cut the include chain, and having all implementation in single cpp file might imporpve link time optimization. Compile time will be shorter (unity build). But it will get messy.

Seems reasonable (if the shorter compile time you're referring to is for re-builds, and not incremental builds), but these techniques you're mentioning don't have much to do with the balanced approach you're disagreeing with.

This was my reasoning why one should prefer to put multiple classes in implementation file instead of header file, if you have a good reason to do so. Personally I usually put classes in their own files.


Btw, there was a bench in internet that 60% of compile time went for writing the .bdp file, and when they split the project all went fast. It wasn't about include chains or repeated opening of files.

You mean splitting every class out to its own pair of files, as compared to shoving everything into only a couple files? Both seem needlessly extreme for practical use. It doesn't seem surprising that they saw improved compile times if they were testing a typical incremental-code-change-and-build pattern of work. Smaller files mean compiling less code per change.

No, I meant they split the project. Most of their time went constructing the .bdp file. Splitting it allowed them the build to multithread better.


I'm talking from experience when our rebuild took over 30min.. and I got it under 10min.

By splitting the project code up into two files per class? You seem to be contradicting your prediction above, that bundling everything together will make a full rebuild faster.

No. I'd advice not to bundle everything together, unless you have good reason to do so (ie if you must). I didn't fix it by unity builds. I fixed it by removing excessive includes of headers.


#4865372 Multiple classes in the same .h and .cpp files

Posted by Codarki on 23 September 2011 - 07:56 PM

I'm sorry I have to disagree again with you VReality. I'd advise to put headers into their own files, and share the implementation in single cpp if you must. Low granularity on headers will cut the include chain, and having all implementation in single cpp file might imporpve link time optimization. Compile time will be shorter (unity build). But it will get messy.

Having a class in single header and single implementation is clear when you have a lot of code.

Btw, there was a bench in internet that 60% of compile time went for writing the .bdp file, and when they split the project all went fast. It wasn't about include chains or repeated opening of files.


#4865369 When To And Not To Use Exceptions?

Posted by Codarki on 23 September 2011 - 07:19 PM

But regardless, it's generally possible to handle those failures in some localized way which doesn't propagate the need for their safe handling throughout the code-base. Exceptions, on the other hand, propagate by design. So due to their nature, even if you intend to use them in a localized way, you either ensure that all code is safe for use in their presence, or open the door to lots of bugs as usage changes over time. Unfortunately, even the approach of exception-proofing code is pretty error prone.

I did agree until this point. Error handling always propagates trough, no matter of the technique. It's just a matter how you do it and if you do it at all.


#4864256 When To And Not To Use Exceptions?

Posted by Codarki on 21 September 2011 - 10:38 AM

You're touching so many things with your post, I might fail to make a coherent response. I might have confused what you were meaning as well, but I think you're a bit confused about error handling aswell. It's a hard topic and everyone are always learning more about it.

Reporting an error and handling the error are different things. The severity of the error itself is context sensitive. Depending of an error, one can always give examples when it is exceptional or not, or how severe it is.

When product is in developement, it is better to fail fast. For programmers it means to break at the point of failure, be it by throwing an exception or failed assertion. For artists it means that the application reports understandable errors about what they did wrong. Artists don't like it when application crashes or aborts for no apparent reason, and programmers don't like to hunt simple artist errors. Errors during developement are usually fatal, and should always be dealt with.

The handling (and not handling) of errors changes when product is released, always. There shouldn't be any developer errors in released product. Even if there were a error originating from logic or content assets, it depends on the product if it should be handled or reported. Detecting and choosing to ignore non-severe errors is same as handling them, since you're effectively putting extra logic for additional and optional codepaths to keep program at valid state. Valid state can ofcourse be whatever programmer wants. Truly ignoring errors and continuing in undefined state is unwise.


You're setting up error code handling and exception handling for different standards.


I'm not sure what that means, but I know I'm not a fan of error codes either.

I meant that you're attacking exceptions for poor reasons. Same exact reasons you mentioned can be used as arguments against returning error codes. You seem to be against general handling of errors, not against any specific techniques to handle them.

I do use exceptions, error codes and assertions all in the same project, differently depending of what phase the project is in. Also depending of the error I will either handle it, shutdown gracefully, or abort the program.

What is considered a fatal error, or very exceptional case, is very context sensitive.


#4863769 Goto here?

Posted by Codarki on 20 September 2011 - 04:53 AM

But the point is that with a little bit of restructure it's every bit as readable as before (significantly, it's readable enough for the logic flaw to jump out at you), with simpler flow control, and no temptation to use a "goto".

In short, no need for "goto" here.

It might be more readable, but that doesn't matter if it's wrong. I think latent already posted working solution at post #3.


#4863767 When To And Not To Use Exceptions?

Posted by Codarki on 20 September 2011 - 04:43 AM

You're setting up error code handling and exception handling for different standards.

The more serious problem is that it's non-trivial to make code 'safe' to use in the presence of exceptions. That is, special care must be taken to assure that the occurrence of an exception doesn't cause code to leave objects in unexpected or invalid states. This “special care” is problematic:

Exceptions are no more problematic than error codes. If you leave objects in invalid states with error codes, you might as well leave them invalid with exceptions. You don't have to handle it.



It's extremely code intrusive.


It's often complained that other approaches to error handling are code intrusive, and that's true. But exceptions are far more intrusive, and in a much more insidious way.

For example, in order for a member function to modify its object in an exception safe manner, it must either make all function calls (which could potentially throw exceptions) first, without changing the state of the object, then use the results to change the object state in ways that are somehow guaranteed not to allow exceptions, or it must catch all possible exceptions that can happen during the change of state, and then reliably restore the object to a valid state, without the possibility of causing any new exceptions in the meantime.

And with error codes you have to do the same, and more, if you want to leave the object in valid state. Or you can leave it in invalid state if you're not handling the error and will be shutting down anyway.


The latter approach is ad hoc, and can't be proven valid. The former approach is complicated by the way language syntax likes to hide function calls. But what's worse, is that it invisibly inserts exception safety coding decisions into just about every line of code written. Any maintenance geared toward the actual functionality of a piece of code is liable to break exception safety just as invisibly. Exception sanitized code will often appear nonsensical, and the only way to try to protect it from being “fixed” (broken, actually) is through a constant barrage of comments about exception safety.

Same can be said about error codes.


In other words, exception safety is a constant intrusion into nearly every line of code written.

So are error codes, you are checking them every line, right?


It's also design intrusive.

For example, if you had a “Stack” class with a “Pop” function that returned the item popped off the stack, theoretically, an exception could be thrown during the copy of the object that gets returned. This means that the stack would have lost the object (having already successfully “popped” it), but the client code would not yet have stored it, which may well represent an invalid program state.

So to allow the clients of a stack class to operate in an exception safe manner, “Pop” and “Get” functionality must be implemented separately. That is, “Pop”, which alters the stack, must not return an item, and “Get”, which returns an item, must not alter the stack.

Exception safety forces design decisions that appear odd and arbitrary. At best this can be confusing and annoying. Much worse is the likelihood that someone will “fix” the design, unknowingly making it “unsafe”.

Can this same be done more elegantly with error codes then?


While we welcome geniuses to our team, the fact is, we have better problems to be solving than exception-proofing code.

Besides, most of these errors, which we'd have to bend over backwards to allow “safely”, are ultimately fatal conditions to our application. By the time they happen, something has already gone wrong enough to prevent the correct function of the program.

It seems our best response to such errors is to trip a debugger break immediately, as near to the cause as possible, so we can diagnose and fix the problem, and ultimately produce code which will no longer result in a fatal condition. In other words, we find the “handling” of most exceptions to be counter-productive, and the all-pervasive labor, of making code “safe” for errors, to be irrelevant.

So if you're not handling errors anyway, I'm a bit confused why you talk so much about exception safety and handling them. Just throw and catch at top level to inform the user?


In addition to the above, unless exception handling is completely disabled for a build, the program must always perform exception handling bookkeeping behind the scenes for every function call ever made.

I think there are zero-overhead exception handling in some compilers, if no exception is thrown.

I think you're trying to do different things with exceptions and error codes. If you want to compare them, do the same thing. I find the reasons about some compilers not supporting them much better.


#4858538 [C++] Looking for feedback on my event system

Posted by Codarki on 07 September 2011 - 03:28 AM

I have only some nitpicking that could possible simplify the public interfaces.

These does not need to be virtual. I think it would be simpler if they weren't.
virtual void SetHandled(bool handled) { handled_ = handled; }
virtual bool IsHandled() const { return handled_; }

Unnecessary code.
Event() {}
virtual ~Event() {}

I find the "Interface" word in the class names redundant.
If the event parameter in EventListener would be a reference, you could omit all checks for null event.
Likewise in EventDispatcher Register method, if the listener parameter would be a reference, it would indicate to the user that the EventDispatcher will not call delete to given listeners.


#4856777 Canceling a Constructor [C++]

Posted by Codarki on 02 September 2011 - 09:11 AM

How about:

class TGATextureData
{
public:
	TGATextureData(const std::vector<char>& data)
	: m_data(data)
	{
	}

private:
	std::vector<char> m_data;
}

TGATextureData* TryLoadTGATextureDataFromFile(const char *filename)
{
	std::vector<char> data;
	// loading the data from the file
	if (!data.empty())
    	return new TGATextureData(data);
	else
    	return 0;
}

Now your texture data class is more simpler. It is always in usable state, so you don't have to check IsLoaded() anymore. It is not tied to the source of the resource (the filesystem), and you could even drop the TGA part from it.

PS. Why not use RAII?


#4847596 To goto or not to goto?

Posted by Codarki on 11 August 2011 - 04:31 AM

I think the ones against goto always use the worst examples of gotos.

And for that reason, here is an example where I personally think it makes good sense to use goto statements (like a replacement for a small inline function):
static MyClass*MyClass::createInstance(void)
{
	MyClass*inst=null;

	if(!(inst=new MyClass()))
    	return null;
	if(!(inst->object1=new Object1()))
    	goto FAILED;
	if(!(inst->object2=new Object2()))
    	goto FAILED;
	if(!(inst->object3=new Object3()))
    	goto FAILED;
	if(!(inst->object4=new Object4()))
    	goto FAILED;

	return inst;

	FAILED:
	{
    	delete inst->object1;
    	delete inst->object2;
    	delete inst->object3;
    	delete inst->object4;
    	delete inst;

    	return null;
	}
}


I think you'r example for goto is pretty bad. How can the allocation of those objects fail without throwing an exception?

static MyClass* MyClass::createInstance()
{
	MyClass* inst = new MyClass();

	if (inst)
	{
    	bool failed = !(inst->object1 = new Object1());
    	if (!failed)
        	failed |= !(inst->object2 = new Object2());
    	if (!failed)
        	failed |= !(inst->object3 = new Object3());
    	if (!failed)
        	failed |= !(inst->object4 = new Object4());

    	if (failed)
    	{
        	delete inst->object1;
        	delete inst->object2;
        	delete inst->object3;
        	delete inst->object4;
        	delete inst;
        	inst = 0;
    	}
	}
 
	return inst;
}

If we use C++, lets write C++. Constructors and destructors and all.

MyClass::MyClass()
: object1(new Object1)
: object2(new Object2)
: object3(new Object3)
: object4(new Object4)
{
}

MyClass::~MyClass()
{
	delete object1;
	delete object2;
	delete object3;
	delete object4;
}

static MyClass* MyClass::createInstance()
{
	return new MyClass();
}
I'd go even further and use std::unique_ptr, so you don't even have to write the destructor.


#4842981 Thread-safe iteration/traversal

Posted by Codarki on 31 July 2011 - 09:23 PM

I'd suggest making as much as possible of use of immutable objects. With immutable objects you don't have to think about thread safety that much, making whole solution much more simpler. With multithreading it's all about the data. Ofcourse there has to be some producer, and it can be created from multiple SPSC queues, to SPMC.

Immutable objects are always thread safe, just use STL, no locking needed.

The file system you mention sounds like a clear case of immutable data. Or is the files and directories changing at runtime?


#4839197 What do you think about the Revelation?

Posted by Codarki on 22 July 2011 - 08:48 PM

I'm amazed we are still talking about this in "modern" age. I find studies about cults and brain washing to be fascinating. How to make people believe and follow whatever is told. Large religions are especially interesting, becouse it's a global issue that touches us all in real life. With millions of followers it kind of feeds itself.

Also I think the globalization is the cause of the misinformation. I don't mean to point blame, but I do think the now popular thing of questioning the evolution is mainly coming from US. It's been approved fact in europe for decades. The religion is cannot be let in politics. Also at some point I thought the Vatican was crazy, but now there seems to be alot of churches in US who doesnt listen or follow what pope says about their religion.

I think we should just quit talking about this.


#4835420 Inheritance Issue

Posted by Codarki on 14 July 2011 - 02:30 PM

I'd suggest against deep inheritance hierarchy, and consider composition. The whole idea of there being a BaseEntity and Entity, and all "entities" in a game inheriting from them, sounds like trouble to me.

class InputEventHandler;
class IdSource; // int GetId()

class Player
{
public:
    Player(InputEventHandler* handler, IdSource* source)
    : handler(handler), source(source)
    {
    }
    InputEventHandler& Handler()
    {
        return *handler;
    }
    IdSource const& IdSource()
    {
        return *source;
    }

private:
    InputEventHandler* handler; // shared_ptr
    IdSource* source; // shared_ptr
};



#4757558 Unsigned Vs. Signed Generally

Posted by Codarki on 11 January 2011 - 10:55 PM

For me, it's unsigned types for all usages which can't logically be negative (like size, count, and the first example in OP). I don't even remember when I got bit by overflow or underflow, I tend to use asserts and exceptions for inputs.


#4531078 boost::intrusive_ptr problem

Posted by Codarki on 23 September 2009 - 06:21 AM

You are missing virtual destructor in Referencable, try if that helps.




PARTNERS