Symbian OS Explained - Effective C++ Programming For Smartphones (2005) (779885), страница 53
Текст из файла (страница 53)
The interface_uid for CResolver is 0x10009D0 – youshould always use this value in the resource file created for your custom resolver.Such a resolver must implement the pure virtual functionsIdentifyImplementationL() and ListAllL() declared inCResolver. It should also specify a factory creation function whichtakes an MPublicRegistry reference parameter; this object gives theresolver access to a list of implementations of a specified interface.IdentifyImplementationL() should be implemented to identifythe most appropriate implementation of a specified interface, accordingto a cue. It will use the MPublicRegistry object to obtain information about each implementation. ListAllL() must return a list of allimplementations which match the cue.class CCryptoResolver : public CResolver{public:// Factory functionstatic CCryptoResolver* NewL(MPublicRegistry& aRegistry);∼CCryptoResolver();public: // From CResolver (see resolver.h)/** Request that the resolver identify the most appropriateinterface implementation, returning the UID or KNullUid if nomatch is found */TUid IdentifyImplementationL(TUid aInterfaceUid,const TEComResolverParams& aAdditionalParameters) const;/** Return a pointer to an array of all the implementations whichsatisfy the specified interface */RImplInfoArray* ListAllL(TUid aInterfaceUid,const TEComResolverParams& aAdditionalParameters) const;...
// Omitted};The custom resolver may be used by the interface instantiation functions; for example, the CCryptoInterface::NewL() factory methodmay be extended to use a custom resolver as follows:CCryptoInterface* CCryptoInterface::NewL(){// The implementation instantiated is the first found by resolver_LIT8(KAny,"*");TEComResolverParams resolverParams;resolverParams.SetDataType(KAny());resolverParams.SetWildcardMatch(ETrue);EXAMPLE CLIENT CODE245// UID of the crypto resolverconst TUid KCustomResolverUid = {0x10008EE6};TAny* cryptoInterface =REComSession::CreateImplementationL(KCCryptoInterfaceUid,_FOFF(CCryptoInterface,iDtor_ID_Key), NULL, resolverParams,KCustomResolverUid));return (reinterpret_cast<CCryptoInterface*>(cryptoInterface));}The third UID of an ECOM plug-in DLL is used to name its associated compiled resource, which contains its ECOM ”registration”information.14.6 Example Client CodeSo how does a client use an ECOM plug-in? As I have already described,the caller doesn’t need to be aware of the details and simply usesthe factory function supplied by the interface, supplying a cue if it isrequired.
ECOM takes care of the details of locating and instantiating theappropriate implementation. An interface client must simply include theheader files which define the interface, link against ECOM.lib and usethe factory instantiation functions as appropriate:#include "CryptoInterface.h"void GetDefaultCryptoL(){// Get the default implementation of CCryptoInterfaceCCryptoInterface* crypto = CCryptoInterface::NewL();CleanupStack::PushL(crypto);...CleanupStack::PopAndDestroy(crypto);}void GetSpecifiedCryptoL(){// Use a cue - gets CCryptoInterface implementation which uses// hardware support_LIT8(KHardware,"HW");CCryptoInterface* crypto = CCryptoInterface::NewL(KHardware);CleanupStack::PushL(crypto);...CleanupStack::PopAndDestroy(crypto);}void GetAllCryptoL(){// Get all implementations using CCryptoInterface::ListImplementationsL()RImplInfoPtrArray infoArray;246ECOMCCryptoInterface::ListImplementationsL(infoArray);// infoArray is not leave-safe, but use of the cleanup stack is// omitted for clarity.
See Chapter 3 for more information....CCryptoInterface* crypto;for (TInt i =0; i< infoArray.Count(); i++){// Retrieves default_data for eachTPtrC8 dataType = infoArray[i]->DataType();crypto = CCryptoInterface::NewL(dataType); // Use this as a cueCleanupStack::PushL(crypto);...CleanupStack::PopAndDestroy(crypto);}}14.7SummaryThis chapter covered the important concepts behind the ECOM architecture, which provides services to locate, resolve, instantiate and manageinstances of polymorphic plug-in DLLs.The chapter discussed how to define an abstract interface and howto implement it in an ECOM plug-in DLL. The example showed howto implement two concrete implementation classes for a fictional cryptographic interface, within a single polymorphic plug-in DLL. For thisreason, an ECOM plug-in DLL is also known as an ”ECOM InterfaceImplementation Collection”, and assigned a targettype of ECOMIIC.The chapter also described how an interface client can use factory methods provided by the interface to instantiate concrete instancesthereof, without having any knowledge of ECOM itself.
The factory instantiation functions, provided by the interface, call the ECOM frameworkusing REComSession::CreateImplementationL(). The ECOMframework uses a default or customized resolver to examine the registryof interface implementations and instantiate an object of the appropriateclass. An interface client should simply include the header files whichdefine the interface and link against ECOM.lib.Chapter 13 discusses generic polymorphic plug-in DLLs and SymbianOS DLL loading in more detail.15PanicsWe experience moments absolutely free from worry. These briefrespites are called panicCullen HightowerOne dictionary definition of panic is ”a sudden overpowering fright;sudden unreasoning terror often accompanied by mass flight”.
The wordpanic itself derives from Pan, the Greek god of nature and goatherds, whowas half man and half goat. He was considered by some to represent animage of the devil. Panic was said to resemble the mental or emotionalstate induced by him.On Symbian OS, when a thread is panicked, the code in it stopsrunning. Panics are used to highlight a programming error in the mostnoticeable way, stopping the thread to ensure that the code is fixed, ratherthan potentially causing serious problems by continuing to run.
There isno recovery from a panic. Unlike a leave, a panic can’t be trapped. Apanic is terminal.If a panic occurs in the main thread of a process, the entire processin which the thread runs will terminate. If a panic occurs in a secondarythread, it is only that thread which closes. However, on hardware, ifany thread is deemed to be a system thread, i.e.
essential for the systemto run, a panic in the thread will reboot the phone.1 Otherwise, if it’snot a system thread, on target hardware and in release builds on theWindows emulator, the end result of a panic is seen as a ”Programclosed” message box, which displays the process name, along with apanic category and error code. In debug emulator builds, you can chooseto break into the code to debug the cause of the panic – this is known asjust-in-time debugging.1Forcing a reboot if a system-critical thread panics is a policy decision rather than ashortcoming of the operating system.248PANICSPanics are used to highlight programming errors by terminating thethread (and, if it is the main thread, the process in which it runs).15.1Just-In-Time DebuggingOn the Windows emulator, in debug builds, you can use the User::SetJustInTime() system function to choose whether a panic kills justthe thread or the whole emulator.
By default, just-in-time debuggingis enabled and a panic will terminate the entire program and enterthe debugger. You can disable this by calling User::SetJustInTime(EFalse), whereupon the panic will appear as it does in releasebuilds and simply terminate the thread in which it occurred with anappropriate message box. Just-in-time debugging can be re-enabled bycalling User::SetJustInTime(ETrue).When just-in-time debugging is enabled, the panic calls a functioncalled ThreadPanicBreakPoint(). This function presents the debugger with an information structure which contains information about theID and name of the thread that panicked, the panic category and reason(which are described shortly), and the name of the thread that caused thepanic.
The function then breaks into the code and launches the debuggerwithin the context of the function that called the panic, using __asm int3. You can use the debugger to look through the call stack to see wherethe panic arose and examine the appropriate state.There are some subtle differences in behavior between Symbian OSv8.0, which contains the new hard real-time kernel (known at the timeof going to press as ”EKA2”, which stands for ”EPOC Kernel Architecture2”) and previous releases of Symbian OS (EKA1).Panics on EKA1A call to the static function User::Panic() panics the currently running thread. A thread may panic any other thread in the system byacquiring an RThread handle to it (as discussed in Chapter 10) and calling RThread::Panic(). Both functions take two parameters: a paniccategory string, which is limited to 16 characters, and an error code,expressed as a TInt.Panics on EKA2A call to the static function User::Panic() panics the currently runningthread.
A thread may panic any thread in the same process by callingRThread::Panic(), but can no longer panic threads in any otherGOOD PANIC STYLE249process.2 The panic functions take a panic category string, which cancontain an unlimited number of characters, and an error code, expressed,as usual, as a TInt.15.2 Good Panic StyleEven without breaking into the debugger, you should still be able to trackdown the cause of a panic using the panic category string and errornumber.
It’s good style to make your panic category string descriptiveand unique, so other developers can locate the string in your header files,and with it, any associated panic error codes (which should also havesuitably descriptive names).Thus, you might have a general panic header file for your library whichincludes the following:// ClangerPanic.h#ifndef __CLANGERPANIC_H__#define __CLANGERPANIC_H__#include <e32base.h>_LIT(KClangerPanic, "CLANGER-ENGINE");enum TClangerEnginePanic{ECorruptBlueStringPudding, // =0,EIronChickenNotInitialized,// =1,EInvalidClangerSetting// =2};static void Panic(TClangerEnginePanic aCategory);#endif // __CLANGERPANIC_H__Which defines the Panic() function separately as follows:static void Panic(TClangerEnginePanic aCategory){User::Panic(KClangerPanic, aCategory);}(You’ll notice by the way that the panic enumeration is a T Classbecause an enumeration is a type. Chapter 1 discusses the differencesbetween class types on Symbian OS and how to use them.)When the library code is passed invalid arguments, it may invokePanic() with the appropriate error code, resulting in a panic and2Except where a server thread uses RMessagePtr to panic a misbehaving client thread.250PANICStermination of the thread in which it is running.