Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


Washu

Member Since 24 Mar 2001
Offline Last Active Today, 01:47 AM

#5236259 Do you comment Above or Below your code?

Posted by Washu on 22 June 2015 - 11:01 PM

Where's the "All of the Above option?

Clearly the appropriate way to comment is as follows:
/*****************************************************************
* Create a turkey *
*****************************************************************/
/**/auto turkey = new Turkey(Color::Blue); // Make a blue turkey!
/*****************************************************************
* Created a turkey *
*****************************************************************/



#5231519 Extremely weird, illogical bug. Part of false if clause executed.

Posted by Washu on 28 May 2015 - 11:56 AM

Description is a WCHAR[128]. You then take the address of that. Then you cast that address, which is a WCHAR **, to a WCHAR *.

The type of &adapterDesc.Description is WCHAR (*)[128], not WCHAR **. The types on either side of the assignment are ultimately different and incompatible, but the pointer is likely going to end up pointing to the first element of the Description array anyway in practice, setting aside all the theoretical problems.


Corrected, and yes while it will probably point to the start of the string, simply casting away errors is usually a sign you've done something stupid.


#5231502 Extremely weird, illogical bug. Part of false if clause executed.

Posted by Washu on 28 May 2015 - 10:34 AM

cardName = reinterpret_cast<WCHAR*>(&adapterDesc.Description);

...

Description is a WCHAR[128]. You then take the address of that. Then you cast that address, which is a WCHAR (*)[128], to a WCHAR *.

And you don't see anything wrong with this?

Next time, instead of just casting your errors away, try reading the error.


#5229724 SetDlgItemText in a loop or function

Posted by Washu on 18 May 2015 - 06:04 PM

Don't do this. You shouldn't interact with Windows controls from a background thread. If it works, it's only by chance.
 
The main thread should wait for messages from the background thread.
Since you're already using C++11 threads, you might use condition_variable to signal across threads, although I'm not sure of the best way to do this (been a while since I used C++ for Windows UI)
 
TBH, if you're writing a windows UI, you'd be better off using C#. You can still use your C++ code (just wrap it in a C++/CLI lib) but the UI code will be much cleaner.


SetDlgItemText sends WM_SETTEXT, which will process it on the proper thread (i.e. the thread with the message handler on it). That being said, there are many other UI actions you can do which are not nearly as nice and thus will result in the wrong behavior. PostMessage/SendMessage though are safe.


#5223073 Write ToLower As Efficient, Portable As Possible

Posted by Washu on 13 April 2015 - 09:12 PM

Hello
 
I am challenging myself to try to attempt to write a function that is as efficient, portable and failsafe as possible. The function is very simple and just converts a string (or wstring) to lower case. Are there any improvements you think I could make and any errors I have done?

It's a linear operation. There's nothing inheritly "fast" or "slow" about converting a string to lowercase. In fact, SPEED is not what I would focus on here, utility is, proper handling of unicode or similar characters is far more important than "speed" in this case. Iterators vs indices: There is literally no difference.... additionally:

#ifdef UNICODE
typedef std::wstring tstring;
typedef std::wstring::npos tnpos;
#else
typedef std::string tstring;
//typedef std::string::npos tnpos;  // throws compiler error?!
#endif

npos is not a type.

tstring toLower(const tstring& str)
{
    // Alternative 1: Returns a copy of a local string so not that efficient.

void toLower(const tstring& inStr, tstring& outStr)
{
    // Alternative 2: Have user define string and pass by reference (this would be faster?)

Move construction and such will eliminate the temporary. Returning vs passing in a reference really provides no difference in this case.
 

	
    unsigned int len = str.length(); 	// use unsigned int so I only have 4 bytes as opposed to 16 for int

On what platform are you where INT is 16 bytes, and UNSIGNED INT is 4 bytes.
 

tstring lower(len, 'a'); // ensure string is correct size to avoid dynamic resizing. Reserve at construction; performing 2 steps at once defintion and reserving - is faster right?
// or use lower.reserve(len);

Why are you creating a string of length "len" initialized to 'a'? You realize that this requires an iteration of the entire contents of the string to fill it with 'a', right?
 

    for (unsigned int i=0; i<len; i++)      // iterate using indexes. Maybe iterators could be more fail safe/efficient/etc.?
	lower[i] = tolower(str[i]);     

Iterators vs Indices: The great non-debate. Use iterators, the code will be far clearer.

Additionally, if you must use a copy:
std::string dest;
dest.reserve(data.length()); //if you MUST avoid the allocation, although, to be honest, for small strings this is unnecessary and for long strings the allocation overhead isn't something to worry about (since you should be doing in place modification instead of copying in those cases)
std::transform(data.begin(), data.end(), std::back_inserter(dest), ::tolower);
Do note how i'm not bothering to deal with unicode strings, as that's a complex bag of worms best dealt with by using a proper strings/language library.


#5219320 Can you have to long of a hash string key.

Posted by Washu on 26 March 2015 - 08:45 AM

Why are you storing GUID's in memory as a string. Store them as a quadruplet of dwords (which is effectively what they are), or use the Win32 GUID structure..


#5218959 c++ count lines in txt file and then read these lines without reopening a file

Posted by Washu on 24 March 2015 - 08:11 PM

Also, for those who are curious as to the memory mapped way... This is a non-modifying version that does not require more than one allocation for the file (again, you can do the same with vector and reserve). As you can see, the code does get more complicated, and we need to use a helper object for storing our ranges. We could have mapped the view with FILE_MAP_COPY, and then modified it (thus not modifying the underlying file), however that would involve an extra copy.
 
#include <iostream>
#include <vector>
#include <memory>
#include <windows.h>

template<class T>
struct basic_string_range {
    T const * startPtr;
    T const * endPtr;
};

typedef basic_string_range<char> string_range;
typedef basic_string_range<wchar_t> wstring_range;

template<class T>
std::basic_ostream<T> & operator <<(std::basic_ostream<T> & out, string_range const & range) {
    return out.write(range.startPtr, range.endPtr - range.startPtr);
}

typedef std::unique_ptr<void, BOOL(__stdcall *)(HANDLE)> safe_handle;
typedef std::unique_ptr<char const, BOOL(__stdcall *)(LPCVOID)> file_pointer;

int main() {
    safe_handle fileHandle(CreateFile(L"text.txt", GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0), CloseHandle);
    auto fileSize = GetFileSize(fileHandle.get(), 0);
    safe_handle mappingHandle(CreateFileMapping(fileHandle.get(), 0, PAGE_READONLY, 0, 0, 0), CloseHandle);
    file_pointer fileView(reinterpret_cast<char const *>(MapViewOfFile(mappingHandle.get(), FILE_MAP_READ, 0, 0, fileSize)), UnmapViewOfFile);
    auto fileViewPtr = fileView.get();

    std::vector<string_range> ptrs;
    string_range range = { fileViewPtr };

    for (size_t i = 1; i < fileSize; ++i) {
        if (fileViewPtr[i] == '\r' || fileViewPtr[i] == '\n') {
            if (i + 1 < fileSize && fileViewPtr[i + 1] == '\n')
                ++i;
            range.endPtr = fileViewPtr + i;
            ptrs.push_back(range);
            if (i + 1 < fileSize) {
                range = { fileViewPtr + i + 1 };
            }
        }
    }
    range.endPtr = fileViewPtr + fileSize;
    ptrs.push_back(range);

    std::cout << "Lines: " << ptrs.size() << std::endl;
    for (auto && ptr : ptrs) {
        std::cout << ptr << std::endl;
    }
}



#5218763 c++ count lines in txt file and then read these lines without reopening a file

Posted by Washu on 24 March 2015 - 08:43 AM

Since we're going crazy with memory mapping, why not just go the C-style route?

- Load the entire file into memory.
- Scan it for newline characters, converting each into a null terminator as you find it.
- Keep the count of each newline you replaced.
- Allocate a char*[] using newline count.
- Loop over the modified file again, setting each pointer to the start of each respective string (the start of the file and at the character following each null terminator). Stop your loop when you hit the newline count you've been tracking.


Why on earth would you do this loop twice, when you can combine both steps into one.... even in C you could simply reallocate the array of pointers if necessary. Telling the size of the file is pretty damn simple too... A C++ version:
 
	std::ifstream fin("somefile.txt", std::ios_base::in);
	fin.seekg(0, fin.end);
	auto length = fin.tellg();
	fin.seekg(0, fin.beg);

	std::vector<char> data;
	data.reserve(length);

	std::vector<size_t> string_offsets;
	string_offsets.push_back(0);

	while (fin) {
		auto ch = fin.get();
		if (ch == '\n') {
			data.push_back(0);
			string_offsets.push_back(data.size());
		}
		else {
			data.push_back(ch);
		}
	}
	data.push_back(0);

	for (auto && offset : string_offsets) {
		std::cout << (&data[0] + offset) << std::endl;
	}



#5217857 Any good cross platform C++ scheduler libraries?

Posted by Washu on 20 March 2015 - 08:30 AM

You should look into Intel's TBB.


#5214222 Vulkan is Next-Gen OpenGL

Posted by Washu on 03 March 2015 - 09:35 AM

why should someone want to use D3D12 ?

 
The reason to prefer D3D has always been more robust drivers and better tools on an API that hits ~95% of the target market.  That's it.  Preference for one vendor or one platform comes nowhere into it, nor do any malicious backdoor shenanigans.  The D3D driver model was simply a better driver model that, once the emotional aspect of the original API war burned out, became obvious to everyone that it allowed for this to happen.  But that's also the hurdle that Vulkan now has to get over (and Khronos are making the right kind of noises about this, which is encouraging).
 
Right now Vulkan seems to have a head-start, and if we can get a spec, sample apps, some functional tools and reasonable drivers from all 3 desktop vendors by SIGGRAPH, it should eat D3D 12.
 
On the other hand if Khronos stall or if the vendors fail to deliver then D3D 12 will have a chance to jump back ahead.
 
Either way the next year is going to be interesting. biggrin.png


Robust tools are a huge winning point there. OpenGL could target 95% of the market as well, but the lack of decent vendor agnostic tools made it a real pain in the keister to use. Using an API where you can actually debug what is going on (PIX for example) is really important. Unfortunately, OpenGL never really had that capability and you were stuck with whatever tools the various GPU vendors provided. Which, frankly, all suck in their own unique ways.

Vulkan certainly looks interesting, but I also recall the LAST TIME we were promised something great OpenGL wise. You might remember how that ended. So at the moment I'm going to go with current mood: Pessimistic without further evidence.


#5209297 Why am I getting Access Violation Reading with XMVector3TransformCoord

Posted by Washu on 07 February 2015 - 01:20 PM

Well interestingly, I did more research and it was told the class address wasn't proply aligned and to use _mm_malloc function. Which I did and it works. I remembered to free the class when done with _mm_free function as well. That's something I learned new today.


In 32 bit mode objects allocated on the heap are aligned to an 8 byte boundary. Meanwhile the non-unaligned load/store operations require paragraph alignment (16 bytes) for cache reasons. As such, sometimes things "might" work when you don't allocate them using an aligned allocator, and some might end up unaligned (as you found out).

In C there's an aligned_alloc function, and in C++ you can use the std::align function to return an aligned pointer from a block of memory (of course, this does require you to allocate sufficient memory to fit the aligned object plus however is necessary to align it). Do note that if you simply point a class at your aligned memory... a constructor will not be called. So if you have non-trivial constructors you need to use placement new, and if you have a non-trivial destructor you will need to invoke that as well.


#5209203 XML Serialization

Posted by Washu on 06 February 2015 - 08:06 PM

Umm..., a quick google on C# XML, will turn up plenty of results.

Other than that you're going to have to be a LOT MORE specific about what you're trying to ask.


#5209193 MASM Assembly Help!

Posted by Washu on 06 February 2015 - 07:17 PM

move AH, 9h


"move" is not a valid opcode.

Additionally, i would recommend learning 32 bit assembly, as 16 bit assembly is pretty much not used anywhere and the architecture of 16 bit mode is pretty much replicated nowhere (so the knowledge isn't even useful on other platforms for the most part)


#5208009 When to use pointers or objects in 'Composition'?

Posted by Washu on 01 February 2015 - 01:52 AM

E.g. if you have a TextureCache object that depends on the Graphics object, make sure it is declared after the Graphics object. Then you can safely pass the Graphics instance to the TextureCache constructor and be sure the TextureCache will be destroyed before the Graphics:

Most modern compilers will warn on this, thankfully.


#5208000 Some programmers actually hate OOP languages? WHAT?!

Posted by Washu on 01 February 2015 - 12:18 AM

In fact, I'm just going to lock this.




PARTNERS