Originally Posted by
CornedBee
By the way, have you considered the overhead of the map thing? A map node is typically 3 pointers and a boolean large (due to alignment, typically 4 pointers, unless ugly tricks are used). Add to that the value type - another pointer plus sizeof(PointerInfo). On a 32 bit system, you get a total of what, 32 bytes? That's a LOT. And it doesn't even count the allocation overhead of the map nodes. Let's say a total of 36 bytes. This may well be about the average of your object size. In other words, unless you use performance critical pointers for most cases, this little gag doubles your memory requirements.
Memory is not an issue.
But since you wanted to know the overhead of the class, here's some statistics for you:
CMemoryManagerStatics, all statics variables:
Code:
class AFX_EXT_CLASS CMemoryManagerStatics
{
public:
std::map<const void*, PointerInfo*> m_InfoMap; // Size: 28 bytes
CCriticalSection cThisMapSync; // Size: 36 bytes
HANDLE hThreadLock; // Size: 4 bytes
CMemoryManagerStatics();
~CMemoryManagerStatics();
};
Total size: 68 byte
Padding: 0 bytes
PointerInfo struct:
Code:
struct PointerInfo
{
DWORD dwRefCount; // Size: 4 bytes
CCriticalSection cSync; // Size: 36 bytes
bool bExistInMap; // Size: 1 byte
bool bThreadSafetyOn; // Size: 1 byte
};
Total size: 42 bytes (44 bytes with padding).
Padding: 2 bytes
CMemoryManager class:
Code:
template<typename T> class CMemoryManager
{
// ...
T* p; // Size: 4 bytes
MemoryManager::PointerInfo* m_pInfo; // Size: 4 bytes
#ifdef _DEBUG
DWORD m_dwThreadId; // Size: 4 bytes
#endif
// ...
}
Total size: 12 bytes (16 bytes with padding)
Padding: 4 bytes
Also remember that statics is a one-time overhead in the DLL ONLY. It's shared by all classes.
The PointerInfo structure is shared by all classes pointing to the same memory, so the general overhead is 16 bytes, and 44 bytes with every new pointer. The biggest suckers are the CCriticalSection object, which is necessary for thread safety.
Here's another one for you: With 100.000 instances of the class, all with unique pointers, the total allocation is 8 800 004 bytes (8.8 MB). On today's systems, that's nothing.
How did I get this info? Simple:
Code:
CMemoryState a,b,c;
a.Checkpoint();
ppnew<int>* p = new ppnew<int>[100000];
pp<int> p7;
b.Checkpoint();
c.Difference(a, b);
c.DumpStatistics();
I'm wading through all this information to see what can be done, right now. I also have another idea for operations on the pointer itself. I'll have to see if it works out alright.
Originally Posted by
Codeplug
You are correct in that
non-instantiated templates can not be exported from a DLL - but instantiated templates can be exported - with a few limitations from MS...
This should cover it:
http://support.microsoft.com/kb/q168958/
Codeplug, that's for the information! I thought it might work if I actually specified a type of the class to be exported, but I never knew how to do it.
Still, I don't think it's a very good idea since it would practically hamper on what objects could be used in the class (and maybe bloat the DLL?).
Each time I wanted to use a new type, I'd get linking errors and would have to modify and recompile the DLL. Sad to say, it's a little unpretty and totally unusable to anyone but myself.
Thanks for the info, though.
Originally Posted by
Codeplug
>> There's no easy way to hide the usage of std::xxx objects...
It's fairly easy to hide any implementation detail. Here's a snippet:
I see. So you're basically hiding the STL classes in custom structs/classes and declaring those structs/classes in the .cpp file, right?