/// <summary> /// Creates a new attribute that will be stored inside the low-level communicator. /// </summary> /// <param name="duplication">How this attribute will be duplicated.</param> /// <param name="onHeap">Whether this attribute will be allocated on the heap.</param> public StoredAttribute(AttributeDuplication duplication, bool onHeap) : base(duplication) { this.onHeap = onHeap; unsafe { Unsafe.MPI_Copy_function copyFn = Unsafe.MPI_NULL_COPY_FN; Unsafe.MPI_Delete_function deleteFn = Unsafe.MPI_NULL_DELETE_FN; #if BROKEN_NULL_DELEGATE copyFn = NullCopy; deleteFn = NullDelete; #endif if (duplication != AttributeDuplication.None) { if (onHeap) { copyFn = DeepCopy; deleteFn = DeleteAttributeMemory; } else { copyFn = ShallowCopy; } } int errorCode = Unsafe.MPI_Keyval_create(copyFn, deleteFn, out keyval, new IntPtr()); if (errorCode != Unsafe.MPI_SUCCESS) { throw Environment.TranslateErrorIntoException(errorCode); } } }
/// <summary> /// Create a new attribute, which can be attached to MPI communicators. /// </summary> /// <typeparam name="T"> /// The type of value that will be stored with the attribute. /// </typeparam> /// <param name="duplication"> /// Describes how (or if) an attribute is copied when a communicator /// is cloned. /// </param> /// <returns> /// A new attribute whose value type is <c>T</c>. This attribute /// can be attached to any communicator. /// </returns> public static Attribute Create <T>(AttributeDuplication duplication) { if (typeof(T).IsValueType) { bool isLarge = Marshal.SizeOf(typeof(T)) > Marshal.SizeOf(typeof(IntPtr)); switch (duplication) { case AttributeDuplication.None: // Since duplication isn't an issue, allocate on the heap // only when the value type is "large" return(new StoredAttribute <T>(duplication, isLarge)); case AttributeDuplication.Shallow: // Small value types are stored directly in the communicator, // and shallow copies are the only option. // For large value types, we handle them like objects with // special holders in them, so that the garbage collector // will keep track of the memory for us. if (!isLarge) { return(new StoredAttribute <T>(duplication, false)); } else { return(new ShallowValueAttribute <T>(duplication)); } case AttributeDuplication.Deep: // For deep copies, small value types are still stored // directly in the communicator (since shallow and deep // copies are identical). Larger value types will be // automatically allocated/deallocated on the heap, // and each communicator will "own" its attribute value. return(new StoredAttribute <T>(duplication, isLarge)); } } // For class types, which need to be on the garbage-collected heap. return(new Attribute(duplication)); }
internal ShallowValueAttribute(AttributeDuplication duplication) : base(duplication) { }
/// <summary> /// Construct a low-level attribute object. /// </summary> internal LowLevelAttribute(AttributeDuplication duplication) : base(duplication) { keyval = Unsafe.MPI_KEYVAL_INVALID; }
/// <summary> /// Creates a new attribute. Users need to use the factory function <see cref="Create"/>. /// </summary> /// <param name="duplication"></param> internal Attribute(AttributeDuplication duplication) { this.Duplication = duplication; }