|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
This article doesn't cover new ATL7 Server Classes and Attributes. This is not a complete list - only what I have found so far. Strings StringsATL3:String conversion macros had a few limitations. It was allocating memory from stack, with potential to overflow the stack with large strings. The string was freed when the function exited and not at any introduced scope inside the function.
It was using outdated USES_CONVERSION;
try
{
for(int i=0; i< 100000; ++i)
LPTSTR str = OLE2T(L"Some string string string string string........");
// stack overflow, memory on the stack grows...
throw int(1); // if above doesn't fail, then make sure catch(int) is executed
}
catch(int)
{
LPTSTR str = OLE2T(L"Some string string string string string........");
// _alloca can't be used in SEH or C++ EH
// Generates Unhandled Exception
// Will be marked as error in VS.NET during compile
}
ATL7: String Conversion macros/classes improve in those areas mentioned above. It uses stack memory for small strings and heap for large strings so there is no stack overflow when stack space is not enough. The string is freed when it's scope ends and not when function exits. Can be used in exception handlers. Can be used in loops (since it can be controlled by scope). A-ANSI/W-Unicode/T-generic To [Constant] A-ANSI/W-Unicode/T-generic. try
{
for(int i=0; i< 100000; ++i)
CW2A str(L"Some string string string string string........");
throw int(1);
}
catch(int)
{
CW2A str(L"Some string string string string string........");
}
Be aware of one caveat. All of the above macros can't be used in same code construct as in ATL3: LPTSTR str = CW2A(L"some string");
The above code is wrong. After that line the temporary object created by CW2AEX is destroyed. // use size 2 for initial string length to make sure stack size // is not enough and heap is used for memory LPCTSTR szr = CW2AEX<2>(L"some string"); szr; // at this line szr should point to garbage CString:
Another Addition is the CStringT< TCHAR, StrTraitATL< TCHAR > > CAtlString; which is redefined based on MFC being used or not to: // #ifdef _AFX typedef CAtlString CString;
The // use CRT and have more functionality CStringT< TCHAR, StrTraitATL< TCHAR, ChTraitsCRT< TCHAR > > or // don't use CRT, but use win32API string functions, (wvsprintf, lstrlen, CharNext, etc) CStringT< TCHAR, StrTraitATL< TCHAR >, ChTraitsOS<TCHAR> >
Another class
etc. So for example: CComHeap comHeap; CAtlStringMgr mg(&comHeap); CString str(&mg); str += "some string";
and we get "String and Text Classes"(MSDN) "ATL/MFC String Conversion Macros"(MSDN) CollectionsATL7 introduces new collection classes. The classes have similar interface as previous MFC collection classes. These are templated classes CAtlArray/CAtlList:// use CStringElementTraits to have a valid comparison for Find CAtlArray<CString, CStringElementTraits<CString> > array; // other traits are CStringRefElementTraits, CStringElementTraitsI CAtlList<CString, CStringElementTraits<CString> > list; list.AddHead(CString("hello")); list.AddHead(CString("string")); POSITION pos = list.Find("hello"); if(pos != NULL) { CString str = list.GetAt(pos); } CAtlMapCAtlMap<CString, int, CStringElementTraits<CString> > map; map.InitHashTable(269); map["key1"] = 2; map["key2"] = 2; int value; if(map.Lookup("key1", value)); CRBTree/CRBMap /CRBMultiMap - Red-Black tree based implementationCRBMap<int, int> rbMap; rbMap.SetAt(10, 20); rbMap.SetAt(30, 40); CRBMap<int, int>::CPair* p = rbMap.Lookup(30); //p->m_key; p->m_value; rbMap.RemoveKey(30); Various other more specialized classes: CAutoPtrArray/CAutoPtrList /CComUnkArray /CHeapPtrList /CInterfaceArray /CInterfaceList "Collection Classes" (MSDN) ThreadingCWorkerThread<Win32ThreadTraits|CRTThreadTraits>:Quick example: class WorkerClass : public IWorkerThreadClient
{
HANDLE m_hEvent;
CWorkerThread<Win32ThreadTraits> m_thread;
public:
WorkerClass()
{
m_thread.Initialize();
m_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_thread.AddHandle(m_hEvent, this, NULL);
}
~WorkerClass()
{
m_thread.RemoveHandle(m_hEvent);
m_thread.Shutdown();
}
void ResumeThread()
{
::SetEvent(m_hEvent);
}
void FreezeThread()
{
::ResetEvent(m_hEvent);
}
private:
// IWorkerThreadClient
HRESULT Execute(DWORD_PTR dwParam, HANDLE hObject)
{
FreezeThread();
return S_OK;
}
HRESULT CloseHandle(HANDLE hHandle)
{
::CloseHandle(hHandle);
return S_OK;
}
};
Then:
{
WorkerClass work;
work.ResumeThread();
Sleep(5000);
work.ResumeThread();
Sleep(5000);
}
And here is imagined usage of struct IDoSomeWork
{
virtual void Work()=0;
};
class Work1 : public IDoSomeWork
{
void Work(){}
};
class Work2 : public IDoSomeWork
{
void Work(){}
};
class ThreadPoolWorker
{
public:
// support for CThreadPool Worker Archetype
typedef IDoSomeWork* RequestType;
BOOL Initialize(void* pvWorkerParam)
{
return TRUE;
}
void Execute(RequestType request, void* pvWorkerParam,OVERLAPPED* pOverlapped)
{
request->Work();
}
void Terminate(void* pvWorkerParam)
{
}
};
{
CThreadPool<ThreadPoolWorker> pool;
pool.Initialize();
IDoSomeWork* pWork1=new Work1();
pool.QueueRequest(pWork1);
IDoSomeWork* pWork2=new Work2();
pool.QueueRequest(pWork2);
Sleep(5000);
delete pWork1; delete pWork2;
}
Memory ManagementCHeapPtr<CComAllocator | CCRTAllocator>:CHeapPtr<int, CComAllocator> ptr; ptr.Allocate(100); // this class is not for arrays of objects, because it doesn't call delete[], // but only delete. CAutoPtr<CString> ptr(new CString("string")); CAutoVectorPtr<CString> pVec(new CString[100]); // this calls delete[] CComGITPtr:
Manages the pointer in GIT table. Creates the GIT and calls the
Memory Management Classes(MSDN) Files
CAtlTemporaryFile file; CAtlFileMapping<char> filemap; file.Create(NULL, GENERIC_READ|GENERIC_WRITE); file.SetSize(1024); filemap.MapFile(file, 1024, 0, PAGE_READWRITE, FILE_MAP_READ|FILE_MAP_WRITE); char* pMem = filemap; strcpy(pMem, "hello"); "File Handling Classes"(MSDN) SecurityATL7 includes wrappers for win32API security. Quick Example:
CSid sidDenied;
sidDenied.LoadAccount("Leo");
CDacl dacl;
// try either deny or allow and see how OpenEvent later on behaves
dacl.AddDeniedAce(sidDenied, GENERIC_ALL);
// dacl.AddAllowedAce(sidDenied, GENERIC_ALL);
CSecurityDesc desc;
desc.SetDacl(dacl);
CSecurityAttributes secattr(desc);
// limit the access rights to the named event
CHandle hEvent(CreateEvent(&secattr, FALSE, FALSE, "NamedEvent"));
// try open it with all access rights
CHandle hEventOpen(OpenEvent(EVENT_ALL_ACCESS, FALSE, "NamedEvent"));
// if deny ace was added above it should fail. If allow ace
// was added, it should succeed
if(GetLastError() == ERROR_ACCESS_DENIED)
ATLTRACE("\n\nAccess denied when opening event\n\n");
CSecurityDesc descCheck;
AtlGetSecurityDescriptor("NamedEvent",SE_KERNEL_OBJECT, &descCheck);
CDacl daclCheck;
descCheck.GetDacl(&daclCheck);
CSid::CSidArray sidarr;
daclCheck.GetAclEntries(&sidarr);
for(UINT i=0; i<sidarr.GetCount(); ++i)
{
ATLTRACE("%s\n", (LPCTSTR)sidarr[i].Sid());
ATLTRACE("%s\n", (LPCTSTR)sidarr[i].AccountName());
ATLTRACE("%s\n", (LPCTSTR)sidarr[i].Domain());
}
"Security Classes"(MSDN) Miscellaneous
#import <libid:20000000C-500A-100B-B005-000000000000> version("2.2") #import "progid:SomeServer.Blah.1" embedded_idl, no_namespace
No more need for
Synchronization wrappers defined in
|
||||||||||||||||||||||