Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Thor 2.0 released!  (Read 379663 times)

0 Members and 4 Guests are viewing this topic.

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: Thor 2.0
« Reply #45 on: April 09, 2012, 08:10:43 pm »
Quote
It doesn't use RTTI. It creates a deleter at initialization, where the dynamic type is known. Using type erasure, it can call it later. I've also implemented this technique in Aurora's CopiedPtr.

Sorry I meant my Resource Manager uses RTTI or fake RTTI internally, not shared_ptr does xD Shoulda been more clear about that, my bad. I always try and provide a way around using built-in C++ RTTI simply because I know people don't like it due to the overhead.

A simplistic fake rtti can reduce the overhead from 40-bytes per class to 1-byte per class that is checked. Don't use it, no overhead. Though it doesn't have the benefits of being able to tell the super class of a reference...You may even be able to take that overhead out if with some template specialisation tricks.
« Last Edit: April 09, 2012, 08:28:24 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

Haikarainen

  • Guest
Re: Thor 2.0
« Reply #46 on: April 09, 2012, 10:58:38 pm »
Nevermind, apparently nullptr is a new 0x feat wich GCC 4.4.1 doesnt support. It's a problem to me since that's the version that the "Codeblocks MinGW-bundle" comes with, and any other version of mingwgcc isnt supported by codeblocks.

So it's codeblocks or thor :/ there should be some kind of workaround. GCC 4.6.x and higher supports nullptr.

Just reformatted my computer, so I needed to recompile all libs etc. Having some trouble compiling Thor.

Compiler log:


Code: [Select]
||=== thor, all ===|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\Detail\PtrOwner.hpp||In member function 'virtual void aur::detail::PtrOwner<T, U, C, D>::dismiss()':|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\Detail\PtrOwner.hpp|85|error: 'nullptr' was not declared in this scope|
<ThorPath>\extlibs\aurora\include\Aurora\Tools\SafeBool.hpp|64|error: 'nullptr' was not declared in this scope|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\CopiedPtr.hpp||In constructor 'aur::CopiedPtr<T>::CopiedPtr()':|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\CopiedPtr.hpp|62|error: 'nullptr' was not declared in this scope|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\CopiedPtr.hpp|93|error: 'nullptr' was not declared in this scope|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\CopiedPtr.hpp||In constructor 'aur::CopiedPtr<T>::CopiedPtr(aur::CopiedPtr<U>&&)':|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\CopiedPtr.hpp|116|error: 'nullptr' was not declared in this scope|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\CopiedPtr.hpp||In member function 'aur::CopiedPtr<T>::operator void (aur::detail::SafeBoolHolder::*)()() const':|
<ThorPath>\extlibs\aurora\include\Aurora\SmartPtr\CopiedPtr.hpp|185|error: 'nullptr' was not declared in this scope|
||=== Build finished: 6 errors, 0 warnings ===|


I understand the compilers whine, the code:

Code: [Select]
virtual void dismiss()
{
pointer = nullptr;
}

nullptr is never defined. Should I define it as NULL somewhere?


« Last Edit: April 09, 2012, 11:04:19 pm by Haikarainen »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Thor 2.0
« Reply #47 on: April 09, 2012, 11:50:15 pm »
@MorleyDev: How can you get a unique ID for a class without RTTI? You need to register the types manually or require a special interface, don't you?


@Haikarainen: Yes, it's quite annoying that nullptr requires g++ 4.6. Concerning other features, the g++ developers were very fast, already in 4.3 they had a first version of variadic templates, while the next version of Visual Studio will still not support them. For nullptr they needed long however, although they already have a builtin __null with similar meanings.

Anyway, NULL won't work because it isn't convertible to the smart pointer types. There is a partial workaround:
#include <memory>

struct nullptr_t
{
        template <typename T>
        operator T* () const
        {
                return 0;
        }

        template <typename C, typename T>
        operator T C::* () const
        {
                return 0;
        }

        template <typename T>
        operator std::shared_ptr<T> () const
        {
                return std::shared_ptr<T>();
        }

        template <typename T>
        operator std::unique_ptr<T> () const
        {
                return std::unique_ptr<T>();
        }
};

const nullptr_t nullptr;
However, it doesn't work for other classes taking std::nullptr_t arguments and some special cases. And I actually hoped to use clean C++11 features, I don't like to start writing workarounds again ;)

Are you sure you can't replace your g++ with a newer version?
« Last Edit: April 09, 2012, 11:51:58 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Haikarainen

  • Guest
Re: Thor 2.0
« Reply #48 on: April 10, 2012, 12:34:53 am »
I could try, tried to run the bundled version of mingw-gcc with a separate standalone one before, but codeblocks sure didn't like it. Wish me luck :D

EDIT: Meant cmake didnt like it, remember now I had to change the pathvar every time i was going to generate makefiles. Successfully compiled, will try to restore that fireparticle effect now ;)
« Last Edit: April 10, 2012, 12:45:33 am by Haikarainen »

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: Thor 2.0
« Reply #49 on: April 10, 2012, 01:14:48 am »
For GCC 4.6, well 4.7 now, you can download it with Mingw for windows at http://nuwen.net/mingw.html

@MorleyDev: How can you get a unique ID for a class without RTTI? You need to register the types manually or require a special interface, don't you?

You can essentially "hash" a type/class like this:

Code: [Select]
template<typename T> std::size_t get_id()
{
static char id;
return reinterpret_cast<std::size_t>(&id);
}

The address of id will be the same for the same values of T, but different for different values of T. It has some problems with dll boundaries, but so does the built in C++ RTTI.

If you wanna cross DLL boundaries, use a functor and provide specialisations with unique ids for each specialisation.
« Last Edit: April 10, 2012, 01:19:26 am by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Thor 2.0
« Reply #50 on: April 10, 2012, 04:16:03 am »
Thank you both! MorleyDev, that's a really great idea :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Silvah

  • Guest
Re: Thor 2.0
« Reply #51 on: April 10, 2012, 01:34:51 pm »
It's a problem to me since that's the version that the "Codeblocks MinGW-bundle" comes with, and any other version of mingwgcc isnt supported by codeblocks.
Untrue. Download a newer GCC, extract it, change the paths in Code::Blocks settings, ???, profit.

It has some problems with dll boundaries, but so does the built in C++ RTTI.
The C++ RTTI doesn't. It's 2012 now, most significant compilers fixed it long ago. That is, assuming you don't have multiple copies of runtime library in the program (if you do, though, you should fix that anyway).

You can essentially "hash" a type/class like this:

Code: [Select]
template<typename T> std::size_t get_id()
{
static char id;
return reinterpret_cast<std::size_t>(&id);
}
Wouldn't it be better to use void* instead of size_t? You don't care about the value, it's just a magic cookie, so void* will work fine, and you avoid an implementation-defined cast.
« Last Edit: April 10, 2012, 01:37:23 pm by Advocatus Diaboli »

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: Thor 2.0
« Reply #52 on: April 10, 2012, 04:27:22 pm »
I was under the impression that with Windows DLLs it's still an issue, in that the comparisons can only reliably be done on the name and not the address of what is returned by typeid(X). I'd consider this a problem, especially if you're using it somewhere that performance matters. If I'm wrong that's great, now they just need to find a way to propagate exceptions across DLLs...

Either way, the purpose of avoiding RTTI tends to be how RTTI still adds ~40bytes of overhead per virtual destructor. As opposed to this, which only adds 1byte of overhead to the static memory per class actually checked. Especially on an embedded system that could really make a difference. And then some programmers just switch it off and refuse to work with it, so whilst you could just say "well screw them then", ideally would want to be able to do something in that situation if you're making a library.

Sure, you could use void*. You could use char*. It's just that makes it clear you're dealing with a pointer, not some magic number. Usually if you return a pointer, then in my opinion it should be expected to do some pointer things to that pointer. Here you aren't and never would need to, unless you were stretching for single bytes to use in the worst possible way in which case the drawing board is over there, go back to it.

The Windows API hides this via a typedef (such as HANDLE), I hide it inside an integer. It's not a problem on any compiler I know of, as one of the requirements of std::size_t is that it is large enough to hold the value of a pointer and casting a pointer to an integer is one of the main uses of reinterpret_cast.
« Last Edit: April 10, 2012, 05:00:25 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

Silvah

  • Guest
Re: Thor 2.0
« Reply #53 on: April 11, 2012, 08:57:58 pm »
I was under the impression that with Windows DLLs it's still an issue, in that the comparisons can only reliably be done on the name and not the address of what is returned by typeid(X). I'd consider this a problem, especially if you're using it somewhere that performance matters.
That's exactly how they implement it, but it's not a problem at all. Performance doesn't matter unless you can prove it does. And if a program spends significant amount of time doing RTTI, it's very likely that the performance is the least concern, because the first thing code should get then is some serious refactoring, not a microoptimization.

they just need to find a way to propagate exceptions across DLLs...
Again, we're not in the nineties anymore. Exceptions fly across DLLs just fine (but see the caveat in my previous post).

Especially on an embedded system that could really make a difference.
On an embedded system, you probably wouldn't use RTTI at all, because there you wouldn't run into a problem that requires (as opposed to "allows, but there are alternatives that work as well") the use RTTI.
Oh, and on some embedded systems, one byte per class is still quite a lot of memory ;)

Usually if you return a pointer, then in my opinion it should be expected to do some pointer things to that pointer.

[...]
The Windows API hides this via a typedef (such as HANDLE)
Handles happen to be represented as pointers, so... how many times did you try to make something pointerish with a handle?

It's not a problem on any compiler I know of, as one of the requirements of std::size_t is that it is large enough to hold the value of a pointer
No, that's a requirement of std::(u)intptr_t. std::size_t is required only to be able to store the size of any object. Because of that, on some systems, mainly those with segmented memory, size_t can be much smaller than a pointer.

And yes, such systems still exist. They're rare nowadays, but they can be found sometimes somewhere in the embedded world nonetheless. Remember that it's you who started talking about embedded platforms ;)

casting a pointer to an integer is one of the main uses of reinterpret_cast.
Yes, but this doesn't invalidate the fact that it's still left implementation-defined by the standard.
« Last Edit: April 11, 2012, 09:05:02 pm by Advocatus Diaboli »

MorleyDev

  • Full Member
  • ***
  • Posts: 219
  • "It is not enough for code to work."
    • View Profile
    • http://www.morleydev.co.uk/
Re: Thor 2.0
« Reply #54 on: April 11, 2012, 09:49:19 pm »
Well it's not 1-byte per class, it's one byte per class which has the get_info function used on it. Still not ideal.

Ah, my bad about the std::size_t. In the actual implementation I use I specifically define a set of integrals such as int32, int64, and I have one defined which is guaranteed to be at least the same size as a void*.

Basically I did a bunch of template specialisations for each possible size and it's all checked by static_asserts at compile-time so if you did try and use it on a system that has issue with it, it'll just not compile. But then that can be overriden by a define and providing the correct specialisations and...I'll never win one of those "small program" challenges since I do way too much template metaprogramming xD

My point about HANDLE was it does hide the fact that it's a void pointer from the user. How many times do you think people even notice it's void*? I could of done typedef void* typekey. I mostly went with std::size_t to demonstrate the concept and because here it works fine and gets across the "not a void*, not to be treated as a void*" concept.

I used reinterpret_cast because it's a copy bit-for-bit into an integer. That's when you use reinterpret_cast.

My actual implementation does some things to hide this inside a class, and has macros and functions to let you completely ignore whether you're using the built in RTTI or this system...again, never gonna win a smallest program contest.

As for string comparisons, I'm of the opinion that if you can avoid string comparisons, avoid them as a matter of design. Especially since a map is going to be a common place to store a typeinfo which means a lot of string comparisons. Heck, my wrapper for standard C++ works by hashing the name first, and comparing that to reduce the number of string comparisons greatly.

Anyhoo, getting waaaaaaaaaay off-topic xD
« Last Edit: April 11, 2012, 10:49:43 pm by MorleyDev »
UnitTest11 - A unit testing library in C++ written to take advantage of C++11.

All code is guilty until proven innocent, unworthy until tested, and pointless without singular and well-defined purpose.

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Thor 2.0
« Reply #55 on: April 12, 2012, 11:08:18 am »
Meanwhile, I have thought about an implementation of a combined resource manager, and it probably won't be a big problem. The old managers are further used in the implementation, and maybe I'll provide them also in the API.

By the way, does the name "ResourceManager" please you? It is somehow unprecise, I also thought about "ResourceCache". In case I provide the specific managers, the general one might be called "MultiResourceCache", although this sounds strange... Do you have other ideas? :)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Lo-X

  • Hero Member
  • *****
  • Posts: 618
    • View Profile
    • My personal website, with CV, portfolio and projects
Re: Thor 2.0
« Reply #56 on: April 12, 2012, 12:39:33 pm »
I've seen a lot of people saying that a class with "Manager" in its name is bad designed.

IMO, that's not always linked and in the case of a RessourceManager it mean exactly what it mean and everybody knows what it is exactly.

If my voice can count, I prefer the "RessourceManager" name.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Thor 2.0
« Reply #57 on: April 12, 2012, 12:54:56 pm »
Some minor thoughts:

- "Provider" would be a slightly more precise name than "Manager"

- If you provide an all-in-one manager, you must still provide the individual ones in the public API, for people who split audio and graphics into independant modules

- Don't bother with sf::Music and its openFromFile function, it's not a candidate for being managed by your class. It would be wrong to share sf::Music instances, you need a new instance everytime you want to play a music. And nothing's pre-loaded anyway, audio data is streamed, so there's no point keeping unused musics.
Laurent Gomila - SFML developer

Silvah

  • Guest
Re: Thor 2.0
« Reply #58 on: April 12, 2012, 09:02:45 pm »
I used reinterpret_cast because it's a copy bit-for-bit into an integer. That's when you use reinterpret_cast.
I assure you I understand why you're using reinterpret_cast. Still, the standard defines the mapping performed by this operator to be implementation-defined. You can't change it. I can't change it. Even the committee would be very loath to change it, as it would take some freedom  from the implementors. What if that freedom makes the code faster on some platform? What if taking it away would make it impossible to implement that operator in a meaningful way?

Heck, my wrapper for standard C++ works by hashing the name first, and comparing that to reduce the number of string comparisons greatly.
Did you check it's actually worthwhile to do that? You know, typically comparing the names is just a fallback, if the pointers are the same there's no string comparison involved. Thus you could be in fact pessimizing the type_info comparison.

Lo-X

  • Hero Member
  • *****
  • Posts: 618
    • View Profile
    • My personal website, with CV, portfolio and projects
Re: Thor 2.0
« Reply #59 on: April 12, 2012, 10:29:14 pm »
- Don't bother with sf::Music and its openFromFile function, it's not a candidate for being managed by your class. It would be wrong to share sf::Music instances, you need a new instance everytime you want to play a music. And nothing's pre-loaded anyway, audio data is streamed, so there's no point keeping unused musics.

Interesting part, I just have to think about how to handle music now  ::)