The Labs \ Source Viewer \ SSCLI \ System.Runtime.Remoting.Contexts \ ArrayWithSize

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. //
  16. // DynamicPropertyHolder manages the dynamically registered properties
  17. // and the sinks contributed by them. Dynamic properties may be registered
  18. // to contribute sinks on a per-object basis (on the proxy or server side)
  19. // or on a per-Context basis (in both the client and server contexts).
  20. //
  21. // See also: RemotingServices.RegisterDynamicSink() API
  22. //
  23. namespace System.Runtime.Remoting.Contexts
  24. {
  25.     using System.Runtime.Remoting;
  26.     using System.Runtime.Remoting.Messaging;
  27.     using System;
  28.     using System.Collections;
  29.     using System.Globalization;
  30.     internal class DynamicPropertyHolder
  31.     {
  32.         private const int GROW_BY = 8;
  33.        
  34.         private IDynamicProperty[] _props;
  35.         private int _numProps;
  36.         private IDynamicMessageSink[] _sinks;
  37.        
  38.         internal virtual bool AddDynamicProperty(IDynamicProperty prop)
  39.         {
  40.             lock (this) {
  41.                 // We have to add a sink specific to the given context
  42.                 CheckPropertyNameClash(prop.Name, _props, _numProps);
  43.                
  44.                 // check if we need to grow the array.
  45.                 bool bGrow = false;
  46.                 if (_props == null || _numProps == _props.Length) {
  47.                     _props = GrowPropertiesArray(_props);
  48.                     bGrow = true;
  49.                 }
  50.                 // now add the property
  51.                 _props[_numProps++] = prop;
  52.                
  53.                 // we need to grow the sinks if we grew the props array or we had thrown
  54.                 // away the sinks array due to a recent removal!
  55.                 if (bGrow) {
  56.                     _sinks = GrowDynamicSinksArray(_sinks);
  57.                 }
  58.                
  59.                 if (_sinks == null) {
  60.                     // Some property got unregistered -- we need to recreate
  61.                     // the list of sinks.
  62.                     _sinks = new IDynamicMessageSink[_props.Length];
  63.                     for (int i = 0; i < _numProps; i++) {
  64.                         _sinks[i] = ((IContributeDynamicSink)_props[i]).GetDynamicSink();
  65.                     }
  66.                 }
  67.                 else {
  68.                     // append the Sink to the existing array of Sinks
  69.                     _sinks[_numProps - 1] = ((IContributeDynamicSink)prop).GetDynamicSink();
  70.                 }
  71.                
  72.                 return true;
  73.                
  74.             }
  75.         }
  76.        
  77.         internal virtual bool RemoveDynamicProperty(string name)
  78.         {
  79.             lock (this) {
  80.                 // We have to remove a property for a specific context
  81.                 for (int i = 0; i < _numProps; i++) {
  82.                     if (_props[i].Name.Equals(name)) {
  83.                         _props[i] = _props[_numProps - 1];
  84.                         _numProps--;
  85.                         // throw away the dynamic sink list
  86.                         _sinks = null;
  87.                         return true;
  88.                     }
  89.                 }
  90.                 throw new RemotingException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_Contexts_NoProperty"), name));
  91.             }
  92.         }
  93.        
  94.         internal virtual IDynamicProperty[] DynamicProperties {
  95.             get {
  96.                 if (_props == null) {
  97.                     return null;
  98.                 }
  99.                 lock (this) {
  100.                     IDynamicProperty[] retProps = new IDynamicProperty[_numProps];
  101.                     Array.Copy(_props, retProps, _numProps);
  102.                     return retProps;
  103.                 }
  104.             }
  105.         }
  106.        
  107.         // We have to do this ArrayWithSize thing instead of
  108.         // separately providing the Array and a Count ... since they
  109.         // may not be in synch with multiple threads changing things
  110.         // We do not want to provide a copy of the array for each
  111.         // call for perf reasons. Besides this is used internally anyways.
  112.         internal virtual ArrayWithSize DynamicSinks {
  113.             get {
  114.                 if (_numProps == 0) {
  115.                     return null;
  116.                 }
  117.                 lock (this) {
  118.                     if (_sinks == null) {
  119.                         // Some property got unregistered -- we need to recreate
  120.                         // the list of sinks.
  121.                         _sinks = new IDynamicMessageSink[_numProps + GROW_BY];
  122.                         for (int i = 0; i < _numProps; i++) {
  123.                             _sinks[i] = ((IContributeDynamicSink)_props[i]).GetDynamicSink();
  124.                         }
  125.                     }
  126.                 }
  127.                 return new ArrayWithSize(_sinks, _numProps);
  128.             }
  129.         }
  130.        
  131.         private static IDynamicMessageSink[] GrowDynamicSinksArray(IDynamicMessageSink[] sinks)
  132.         {
  133.             // grow the array
  134.             int newSize = (sinks != null ? sinks.Length : 0) + GROW_BY;
  135.             IDynamicMessageSink[] newSinks = new IDynamicMessageSink[newSize];
  136.             if (sinks != null) {
  137.                 // Copy existing properties over
  138.                 // Initial size should be chosen so that this rarely happens
  139.                 Array.Copy(sinks, newSinks, sinks.Length);
  140.             }
  141.             return newSinks;
  142.         }
  143.        
  144.         static internal void NotifyDynamicSinks(IMessage msg, ArrayWithSize dynSinks, bool bCliSide, bool bStart, bool bAsync)
  145.         {
  146.             for (int i = 0; i < dynSinks.Count; i++) {
  147.                 if (bStart == true) {
  148.                     dynSinks.Sinks[i].ProcessMessageStart(msg, bCliSide, bAsync);
  149.                 }
  150.                 else {
  151.                     dynSinks.Sinks[i].ProcessMessageFinish(msg, bCliSide, bAsync);
  152.                 }
  153.             }
  154.         }
  155.        
  156.         static internal void CheckPropertyNameClash(string name, IDynamicProperty[] props, int count)
  157.         {
  158.             for (int i = 0; i < count; i++) {
  159.                 if (props[i].Name.Equals(name)) {
  160.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DuplicatePropertyName"));
  161.                 }
  162.             }
  163.         }
  164.        
  165.         static internal IDynamicProperty[] GrowPropertiesArray(IDynamicProperty[] props)
  166.         {
  167.             // grow the array of IContextProperty objects
  168.             int newSize = (props != null ? props.Length : 0) + GROW_BY;
  169.             IDynamicProperty[] newProps = new IDynamicProperty[newSize];
  170.             if (props != null) {
  171.                 // Copy existing properties over.
  172.                 Array.Copy(props, newProps, props.Length);
  173.             }
  174.             return newProps;
  175.         }
  176.        
  177.     }
  178.     //class DynamicPropertyHolder
  179.     // Used to return a reference to an array and the current fill size
  180.     // in cases where it is not thread safe to provide this info as two
  181.     // separate properties. This is for internal use only.
  182.     internal class ArrayWithSize
  183.     {
  184.         internal IDynamicMessageSink[] Sinks;
  185.         internal int Count;
  186.         internal ArrayWithSize(IDynamicMessageSink[] sinks, int count)
  187.         {
  188.             Sinks = sinks;
  189.             Count = count;
  190.         }
  191.     }
  192.    
  193. }

Developer Fusion