예제 #1
0
        /// <summary>
        /// Sends a message to all matching listeners. This method is thread-safe!
        /// </summary>
        /// <param name="message">The message with the channel and command.</param>
        /// <param name="kind">The matching kind of listeners. Thus, you can send a message only to Ocean servers, component servers or to both.</param>
        /// <returns>All received answers.</returns>
        public IEnumerable<IICCCMessage> send2All(IICCCMessage message, byte kind)
        {
            // No message? No answer!
            if(message == null)
            {
                return new IICCCMessage[0];
            }

            // We read the cache, thus, ensure the read access:
            this.cacheLock.EnterReadLock();
            try
            {
                // Convert the message to data:
                var data = ICCCProcessor.INSTANCE.convertMessage2Data(message);

                // No valid message?
                if(data == null || data.Count < 2) // channel + command = 2
                {
                    return new IICCCMessage[0];
                }

                // Get all matching listeners:
                var matchingListeners = this.icccListenerCache.Where(n => n.IsActive && (kind == ICCCKind.KindALL || n.Kind == kind)).Where(n => n.Channel == message.getChannel() && n.Command == message.getCommand()).ToArray();

                // No matching listener?
                if(matchingListeners.Length == 0)
                {
                    return new IICCCMessage[0];
                }

                // Space for all threads and results:
                var tasks = new Task<IICCCMessage>[matchingListeners.Length];

                // Loop over all matching listeners:
                for(var n = 0; n < matchingListeners.Length; n++)
                {
                    // Get an listener:
                    var listener = matchingListeners[n];

                    // Start a new thread:
                    tasks[n] = Task.Run<IICCCMessage>(() =>
                    {
                        // Send the message and read the answer:
                      	var answerData = this.sendMessage(data, listener);

                      	// Create another empty instance for the answer:
                      	var type = message.getAnswerObject().GetType();
                      	var answerObj = type.GetConstructors().First(info => !info.GetParameters().Any()).Invoke(null) as IICCCMessage;

                      	// Create the answer's message and return it:
                      	return ICCCProcessor.INSTANCE.convertData2Message(answerData, answerObj);
                    });
                }

                // Wait for all answers:
                Task.WaitAll(tasks);
                return tasks.Where(n => n.Result != null).Select(t => t.Result).ToArray();
            }
            catch
            {
                return new IICCCMessage[0];
            }
            finally
            {
                this.cacheLock.ExitReadLock();
            }
        }
예제 #2
0
        /// <summary>
        /// Sends a message to any matching listener. This method is thread-safe!
        /// </summary>
        /// <param name="message">The message with the channel and command.</param>
        /// <param name="kind">The matching kind of listeners. Thus, you can send a message only to an Ocean server, component server or to both.</param>
        /// <returns>The received answer or null.</returns>
        public IICCCMessage send2Any(IICCCMessage message, byte kind)
        {
            // No message? No answer!
            if(message == null)
            {
                return null;
            }

            // We read the cache, thus, ensure the read access:
            this.cacheLock.EnterReadLock();
            try
            {
                // Convert the message to data:
                var data = ICCCProcessor.INSTANCE.convertMessage2Data(message);

                // No valid message?
                if(data == null || data.Count < 2) // channel + command = 2
                {
                    return null;
                }

                // Get all matching listeners:
                var matchingListeners = this.icccListenerCache.Where(n => n.IsActive && (kind == ICCCKind.KindALL || n.Kind == kind)).Where(n => n.Channel == message.getChannel() && n.Command == message.getCommand()).ToArray();

                // The chosen listener:
                var chosenListener = null as ICCCListener;

                // No matching listener?
                if(matchingListeners.Length == 0)
                {
                    return null;
                }

                if(matchingListeners.Length == 1)
                {
                    // Take the only one:
                    chosenListener = matchingListeners[0];
                }
                else
                {
                    // Choose a random listener:
                    chosenListener = matchingListeners[BetterRND.INSTANCE.nextInt(0, matchingListeners.Length)];
                }

                // Send the message and read the answer:
              	var answerData = this.sendMessage(data, chosenListener);

              	// Create the answer's message and return it:
              	return ICCCProcessor.INSTANCE.convertData2Message(answerData, message.getAnswerObject());
            }
            catch
            {
                return null;
            }
            finally
            {
                this.cacheLock.ExitReadLock();
            }
        }