Esempio n. 1
0
 /// <summary>
 /// Injects a channel into the current scope, by looking in the parent scope.
 /// This is particularly useful in isolated scopes, to selectively forward channels
 /// </summary>
 /// <param name="names">The names of the channel to create.</param>
 /// <param name="parent">The scope to look in, <code>null</code> means the current parent</param>
 public void InjectChannelsFromParent(IEnumerable <string> names, ChannelScope parent = null)
 {
     foreach (var n in names)
     {
         InjectChannelFromParent(n, parent);
     }
 }
Esempio n. 2
0
 /// <summary>
 /// Handler method to create a profiling channel
 /// </summary>
 /// <returns>The profiling channel.</returns>
 /// <param name="scope">The scope calling the method.</param>
 /// <param name="attr">The channel attribute.</param>
 /// <param name="type">The type to create the channel for</param>
 private static IUntypedChannel Creator(ChannelScope scope, ChannelNameAttribute attr, Type type)
 {
     return
         ((IUntypedChannel)typeof(ProfilerChannelScope)
          .GetMethod(nameof(CreateProfilingChannel), System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.NonPublic)
          .MakeGenericMethod(type)
          .Invoke(scope, new object[] { attr }));
 }
Esempio n. 3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CoCoL.ChannelScope"/> class that derives from a parent scope.
 /// </summary>
 /// <param name="parent">The parent scope.</param>
 /// <param name="isolated"><c>True</c> if this is an isolated scope, <c>false</c> otherwise</param>
 private ChannelScope(ChannelScope parent, bool isolated)
 {
     ParentScope = parent;
     Isolated    = isolated;
     Current     = this;
     lock (__lock)
         __scopes[m_instancekey] = this;
 }
Esempio n. 4
0
        /// <summary>
        /// Wires up all named channels using the supplied scope
        /// </summary>
        /// <param name="items">The processes to wire up.</param>
        /// <param name="scope">The current scope.</param>
        public static ChannelScope AutoWireChannels <T>(IEnumerable <T> items, ChannelScope scope = null)
        {
            scope = scope ?? ChannelScope.Current;
            foreach (var p in items)
            {
                AutoWireChannelsDirect(p, scope);
            }

            return(scope);
        }
Esempio n. 5
0
        /// <summary>
        /// Injects a channel into the current scope, by looking in the parent scope.
        /// This is particularly useful in isolated scopes, to selectively forward channels
        /// </summary>
        /// <param name="name">The name of the channel to create.</param>
        /// <param name="parent">The scope to look in, <code>null</code> means the current parent</param>
        public void InjectChannelFromParent(string name, ChannelScope parent = null)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentNullException(nameof(name));
            }
            parent = parent ?? this.ParentScope;

            lock (__lock)
            {
                var c = parent.RecursiveLookup(name);
                m_lookup[name] = c ?? throw new ArgumentException($"No channel with the name \"{name}\" was found in the parent scope", nameof(name));
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Gets or creates a named channel.
        /// </summary>
        /// <returns>The named channel.</returns>
        /// <param name="name">The name of the channel to find.</param>
        /// <param name="buffersize">The number of buffers in the channel.</param>
        /// <param name="scope">The scope to create a named channel in, defaults to null which means the current scope</param>
        /// <param name="maxPendingReaders">The maximum number of pending readers. A negative value indicates infinite</param>
        /// <param name="maxPendingWriters">The maximum number of pending writers. A negative value indicates infinite</param>
        /// <param name="pendingReadersOverflowStrategy">The strategy for dealing with overflow for read requests</param>
        /// <param name="pendingWritersOverflowStrategy">The strategy for dealing with overflow for write requests</param>
        /// <param name="broadcast"><c>True</c> will create the channel as a broadcast channel, the default <c>false</c> will create a normal channel</param>
        /// <param name="initialBroadcastBarrier">The number of readers required on the channel before sending the first broadcast, can only be used with broadcast channels</param>
        /// <param name="broadcastMinimum">The minimum number of readers required on the channel, before a broadcast can be performed, can only be used with broadcast channels</param>
        /// <typeparam name="T">The channel type.</typeparam>
        public static IChannel <T> GetChannel <T>(string name, int buffersize = 0, ChannelScope scope = null, int maxPendingReaders = -1, int maxPendingWriters = -1, QueueOverflowStrategy pendingReadersOverflowStrategy = QueueOverflowStrategy.Reject, QueueOverflowStrategy pendingWritersOverflowStrategy = QueueOverflowStrategy.Reject, bool broadcast = false, int initialBroadcastBarrier = -1, int broadcastMinimum = -1)
        {
            if (!broadcast && (initialBroadcastBarrier >= 0 || broadcastMinimum >= 0))
            {
                throw new ArgumentException(string.Format("Cannot set \"{0}\" or \"{1}\" unless the channel is a broadcast channel", "initialBroadcastBarrier", "broadcastMinimum"));
            }

            var attr =
                broadcast
                                ? new BroadcastChannelNameAttribute(name, buffersize, ChannelNameScope.Local, maxPendingReaders, maxPendingWriters, pendingReadersOverflowStrategy, pendingWritersOverflowStrategy, initialBroadcastBarrier, broadcastMinimum)
                                : new ChannelNameAttribute(name, buffersize, ChannelNameScope.Local, maxPendingReaders, maxPendingWriters, pendingReadersOverflowStrategy, pendingWritersOverflowStrategy);

            return(GetChannel <T>(attr, scope));
        }
Esempio n. 7
0
        /// <summary>
        /// Wires up all named channels using the supplied scope.
        /// Checks if the supplied item is an IEnumerable and iterates it
        /// if possible
        /// </summary>
        /// <param name="item">The item to wire up.</param>
        /// <param name="scope">The current scope.</param>
        public static T AutoWireChannels <T>(T item, ChannelScope scope = null)
        {
            // Due to the type matching, we can end up here when
            // the user supplies an array or similar

            // The encapsulation ensures that we only expand the single
            // outer most instance
            if (typeof(System.Collections.IEnumerable).IsAssignableFrom(typeof(T)))
            {
                var en = item as System.Collections.IEnumerable;
                foreach (var x in en)
                {
                    AutoWireChannelsDirect(x, scope);
                }
            }

            return(AutoWireChannelsDirect(item));
        }
Esempio n. 8
0
        /// <summary>
        /// Injects a channel into the current scope, by looking in the parent scope.
        /// This is particularly useful in isolated scopes, to selectively forward channels
        /// </summary>
        /// <param name="name">The name of the channel to create.</param>
        /// <param name="parent">The scope to look in, <code>null</code> means the current parent</param>
        public void InjectChannelFromParent(string name, ChannelScope parent = null)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ArgumentNullException("name");
            }
            parent = parent ?? this.ParentScope;

            lock (__lock)
            {
                var c = parent.RecursiveLookup(name);
                if (c == null)
                {
                    throw new Exception(string.Format("No channel with the name {0} was found in the parent scope"));
                }

                m_lookup[name] = c;
            }
        }
Esempio n. 9
0
 /// <summary>
 /// Wires up all named channels using the supplied scope
 /// </summary>
 /// <param name="item">The item to wire up.</param>
 /// <param name="scope">The current scope.</param>
 public static IProcess AutoWireChannels(this IProcess item, ChannelScope scope = null)
 {
     return(AutoWireChannelsDirect <IProcess>(item, scope));
 }
Esempio n. 10
0
 /// <summary>
 /// Wires up all named channels using the supplied scope
 /// </summary>
 /// <param name="items">The processes to wire up.</param>
 /// <param name="scope">The current scope.</param>
 public static ChannelScope AutoWireChannels(this IEnumerable <IProcess> items, ChannelScope scope = null)
 {
     return(AutoWireChannels <IProcess>(items, scope));
 }
Esempio n. 11
0
        /// <summary>
        /// Wires up all named channels using the supplied scope for the given element.
        /// Does not check if the given item is an IEnumerable
        /// </summary>
        /// <param name="item">The item to wire up.</param>
        /// <param name="scope">The current scope.</param>
        public static T AutoWireChannelsDirect <T>(T item, ChannelScope scope = null)
        {
            // TODO: Throw an exception if we have no channels to wire and item != null ?

            scope = scope ?? ChannelScope.Current;

            foreach (var c in GetAllFieldAndPropertyValuesOfType <IRetireAbleChannel>(item))
            {
                try
                {
                    var marker = c.Value as ChannelNameMarker;

                    // Make sure we do not continue with a marker class instance
                    if (marker != null)
                    {
                        if (c.Key is FieldInfo fi)
                        {
                            fi.SetValue(item, null);
                        }
                        else if (c.Key is PropertyInfo pi)
                        {
                            pi.SetValue(item, null);
                        }
                        else
                        {
                            throw new InvalidOperationException("Marker was neither a field nor a property");
                        }
                    }


                    var autocreate = true;

                    // Skip if already assigned
                    if (c.Value != null && !(c.Value is ChannelNameMarker))
                    {
                        autocreate = false;
                    }

                    var attr = c.Key.GetCustomAttribute(typeof(ChannelNameAttribute), true) as ChannelNameAttribute;

                    // Override if we get a marker
                    if (attr == null && marker != null)
                    {
                        attr = marker.Attribute;
                    }

                    // Skip if the channel does not have a name
                    if (attr == null || string.IsNullOrWhiteSpace(attr.Name))
                    {
                        autocreate = false;
                    }

                    var channelType = c.Key is FieldInfo ? ((FieldInfo)c.Key).FieldType : ((PropertyInfo)c.Key).PropertyType;

                    if (autocreate)
                    {
                        // Figure out what type of channel we expect
                        var readInterface = new [] { channelType }.Union(channelType.GetInterfaces()).Where(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == (typeof(IReadChannel <>))).FirstOrDefault();
                        var writeInterface = new [] { channelType }.Union(channelType.GetInterfaces()).Where(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == (typeof(IWriteChannel <>))).FirstOrDefault();

                        if (readInterface == null && writeInterface == null)
                        {
                            throw new ArgumentException(string.Format("Item {0} had a channelname attribute but is not of the channel type", c.Key.Name));
                        }

                        var isOnlyReadOrWrite = (readInterface == null) != (writeInterface == null);

                        // Extract the channel data type
                        Type dataType = (readInterface ?? writeInterface).GenericTypeArguments[0];

                        // Honor scope requirements
                        var curscope = scope;
                        if (attr.TargetScope == ChannelNameScope.Parent)
                        {
                            curscope = scope.ParentScope ?? curscope;
                        }
                        else if (attr.TargetScope == ChannelNameScope.Global)
                        {
                            curscope = ChannelScope.Root;
                        }

                        // Instantiate or fetch the channel
                        var chan = curscope.GetOrCreate(attr, dataType);

                        if (isOnlyReadOrWrite)
                        {
                            if (readInterface != null && channelType.IsAssignableFrom(typeof(IReadChannelEnd <>).MakeGenericType(dataType)))
                            {
                                chan = (IRetireAbleChannel)typeof(ChannelExtensions).GetMethod("AsReadOnly").MakeGenericMethod(dataType).Invoke(null, new object[] { chan });
                            }
                            else if (writeInterface != null && channelType.IsAssignableFrom(typeof(IWriteChannelEnd <>).MakeGenericType(dataType)))
                            {
                                chan = (IRetireAbleChannel)typeof(ChannelExtensions).GetMethod("AsWriteOnly").MakeGenericMethod(dataType).Invoke(null, new object[] { chan });
                            }
                        }

                        // Assign the channel to the field or property

                        if (c.Key is FieldInfo fi)
                        {
                            fi.SetValue(item, chan);
                        }
                        else if (c.Key is PropertyInfo pi)
                        {
                            pi.SetValue(item, chan);
                        }
                        else
                        {
                            throw new InvalidOperationException("Item is neither field nor property");
                        }

                        JoinChannel(chan, channelType);
                    }
                    else
                    {
                        JoinChannel(c.Value, channelType);
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine("Failed to set channel: {1}, message: {0}", ex, c.Key.Name);
                }
            }

            //TODO: Support Enumerables too?
            foreach (var c in GetAllFieldAndPropertyValuesOfType <Array>(item))
            {
                for (var i = 0; i < c.Value.Length; i++)
                {
                    try
                    {
                        JoinChannel(c.Value.GetValue(i), (c.Key is FieldInfo ? ((FieldInfo)c.Key).FieldType : ((PropertyInfo)c.Key).PropertyType).GetElementType());
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine("Failed to join channel: {1}, message: {0}", ex, c.Key.Name);
                    }
                }
            }

            return(item);
        }
Esempio n. 12
0
 /// <summary>
 /// Static initializer to control the creation order
 /// </summary>
 static ChannelScope()
 {
     __lock = new object();
     Root   = new ChannelScope(null, true);
 }
Esempio n. 13
0
 /// <summary>
 /// Creates a channel, possibly unnamed.
 /// If a channel name is provided, the channel is created in the supplied scope.
 /// If a channel with the given name is already found in the supplied scope, the named channel is returned.
 /// </summary>
 /// <returns>The channel.</returns>
 /// <param name="name">The name of the channel, or null.</param>
 /// <param name="buffersize">The number of buffers in the channel.</param>
 /// <param name="scope">The scope to create a named channel in, defaults to null which means the current scope</param>
 /// <param name="maxPendingReaders">The maximum number of pending readers. A negative value indicates infinite</param>
 /// <param name="maxPendingWriters">The maximum number of pending writers. A negative value indicates infinite</param>
 /// <param name="pendingReadersOverflowStrategy">The strategy for dealing with overflow for read requests</param>
 /// <param name="pendingWritersOverflowStrategy">The strategy for dealing with overflow for write requests</param>
 /// <param name="broadcast"><c>True</c> will create the channel as a broadcast channel, the default <c>false</c> will create a normal channel</param>
 /// <param name="initialBroadcastBarrier">The number of readers required on the channel before sending the first broadcast, can only be used with broadcast channels</param>
 /// <param name="broadcastMinimum">The minimum number of readers required on the channel, before a broadcast can be performed, can only be used with broadcast channels</param>
 /// <typeparam name="T">The channel type.</typeparam>
 public static IChannel <T> Create <T>(string name = null, int buffersize = 0, ChannelScope scope = null, int maxPendingReaders = -1, int maxPendingWriters = -1, QueueOverflowStrategy pendingReadersOverflowStrategy = QueueOverflowStrategy.Reject, QueueOverflowStrategy pendingWritersOverflowStrategy = QueueOverflowStrategy.Reject, bool broadcast = false, int initialBroadcastBarrier = -1, int broadcastMinimum = -1)
 {
     return(ChannelManager.CreateChannel <T>(name, buffersize, scope, maxPendingReaders, maxPendingWriters, pendingReadersOverflowStrategy, pendingWritersOverflowStrategy, broadcast, initialBroadcastBarrier, broadcastMinimum));
 }
Esempio n. 14
0
 /// <summary>
 /// Gets or creates a named channel.
 /// </summary>
 /// <returns>The named channel.</returns>
 /// <param name="attr">The attribute describing the channel.</param>
 /// <param name="scope">The scope to create a named channel in, defaults to null which means the current scope</param>
 /// <typeparam name="T">The channel type.</typeparam>
 public static IChannel <T> Get <T>(ChannelNameAttribute attr, ChannelScope scope = null)
 {
     return(ChannelManager.GetChannel <T>(attr, scope));
 }
Esempio n. 15
0
 /// <summary>
 /// Gets or creates a named channel.
 /// </summary>
 /// <returns>The named channel.</returns>
 /// <param name="attr">The attribute describing the channel.</param>
 /// <param name="scope">The scope to create a named channel in, defaults to null which means the current scope</param>
 /// <typeparam name="T">The channel type.</typeparam>
 public static IChannel <T> GetChannel <T>(ChannelNameAttribute attr, ChannelScope scope = null)
 {
     return((scope ?? ChannelScope.Current).GetOrCreate <T>(attr));
 }
Esempio n. 16
0
 /// <summary>
 /// Creates a channel, possibly unnamed.
 /// If a channel name is provided, the channel is created in the supplied scope.
 /// If a channel with the given name is already found in the supplied scope, the named channel is returned.
 /// </summary>
 /// <returns>The named channel.</returns>
 /// <param name="attr">The attribute describing the channel.</param>
 /// <param name="scope">The scope to create a named channel in, defaults to null which means the current scope</param>
 /// <typeparam name="T">The channel type.</typeparam>
 public static IChannel <T> CreateChannel <T>(ChannelNameAttribute attr, ChannelScope scope = null)
 {
     return(GetChannel <T>(attr, scope));
 }