Wednesday, November 4, 2009

Chapter 8 -- Marshal-by-Value


3 4



Chapter 8



Marshal-by-Value





IA*�piA;��//�interface�pointer�to�interface�IA�of�object�A
IB*�piB;��//�interface�pointer�to�interface�IB�of�object�B

piB->Foo(piA);



When method Foo executes in the context of object B, its single parameter represents the same object A as piA does in the context of the caller of Foo. A fundamental tenet of the COM+ programming model, standard marshaling preserves identity. Said another way, object references are identity invariant under the operation of a COM+ interface method invocation. The following graphic shows the way in which identity invariance is achieved.









While most developers actually don't think of it that way, they find identity invariance an intuitive concept. This is probably because COM+ simply extends the semantics of procedural programming languages. For example, passing an object reference in Microsoft Visual Basic, Java, or C++ gives the callee access to the very same object instance the caller dealt with. But offering services such as location transparency, synchronization transparency, security, and transaction management while simultaneously preserving object identity at times forces COM+ interceptors to do a great deal of work. Yes, you can pass an interface pointer across machines, but each method invocation would involve a round- trip on the network. Object identity preservation comes for free to the compiler of a procedural programming language but can be quite expensive for COM+ middleware. Therefore as simple and basic as the identity-preserving interface method call model might be, it does not perform well enough under certain
conditions.



An object is said to be custom marshaled if it implements the IMarshal interface. When doing so, an object assumes responsibility for defining the meaning of passing interface pointers to the object among contexts, apartments, processes, and machines. By far, the most popular IMarshal implementation is marshal-by-value (MBV). MBV defines the act of passing interface pointers as one of copying the object to which the interface pointer points. The source object implements IMarshal by instructing the remoting machinery to construct an object of its own class in the target context and by writing its entire state to the marshaling buffer. The target object then initializes itself from this state, and we end up with two copies of the same object with initially identical state. MBV copies objects pointed to by interface pointers that appear as parameters to interface methods implemented by standard proxies from the context of the proxy to the context of the proxy's object. That's because it is the
standard marshaling architecture that queries an object for IMarshal in the first place when determining how to move an interface pointer from one context to another.



If object A in our example marshals by value, the parameter of object B's Foo method always will hold an interface pointer to an object that shares object B's context. Whether piA in the scope of Foo is identical to piA in the caller depends on whether the caller shares object B's context. If it does, no copy of object A is made. If it does not, a copy of object A is made when piA is marshaled from the caller's context to object B's context during the call to object B's Foo method, as shown in Figure 8-1. If object B marshals by value, object B and its caller share the identity of object A denoted by piA. This is because object B must reside in the context of its caller. Object A, however, can reside in a different context.








Figure 8-1. MBV requires at least two separate contexts and a standard proxy.




My first goal in this chapter is to discuss the circumstances under which you should consider MBV in your projects. By the time you are done with this chapter, you will be able to answer these questions: exactly which problem does MBV solve? When is it better than other solutions? Second, contrary to popular opinion, MBV is actually rather difficult to implement correctly in general. I will show you what to require of an MBV implementation, walk you through the pitfalls of implementing MBV, and present a complete, reusable MBV class.



No comments: