コード例 #1
0
ファイル: Channel.cs プロジェクト: zhaopan-vip/ZYSOCKET
        /// <summary>
        /// Sends a value over the channel. If no other <see cref="MicroThread"/> is waiting for data, the sender will be blocked.
        /// If someone was waiting for data, which of the sender or receiver continues next depends on <see cref="Preference"/>.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <returns>Awaitable data.</returns>
        public ChannelMicroThreadAwaiter <T> Set <T>(T data)
        {
            Type key = typeof(T);

            if (!receivers.ContainsKey(key) || (receivers.ContainsKey(key) && receivers[key].Count == 0))
            {
                // Nobody receiving, let's wait until something comes up
                var microThread        = MicroThread.Current;
                var waitingMicroThread = ChannelMicroThreadAwaiter <T> .New(microThread);

                waitingMicroThread.Result = data;

                if (senders.ContainsKey(key))
                {
                    senders[key].Enqueue(waitingMicroThread);
                    return(waitingMicroThread);
                }
                else
                {
                    ConcurrentQueue <ChannelMicroThreadAwaiterBase> tmp = new ConcurrentQueue <ChannelMicroThreadAwaiterBase>();
                    senders.AddOrUpdate(key, tmp, (a, b) => tmp);
                    senders[key].Enqueue(waitingMicroThread);
                    return(waitingMicroThread);
                }
            }

            ChannelMicroThreadAwaiterBase receiverbase;

            if (receivers[key].TryDequeue(out receiverbase))
            {
                var receiver = receiverbase as ChannelMicroThreadAwaiter <T>;
                receiver.Result = data;
                if (Preference == ChannelPreference.PreferSender)
                {
                    receiver.MicroThread.ScheduleContinuation(ScheduleMode.Last, receiver.Continuation);
                }
                else if (Preference == ChannelPreference.PreferReceiver)
                {
                    receiver.MicroThread.ScheduleContinuation(ScheduleMode.First, receiver.Continuation);
                    // throw new NotImplementedException();
                    //await Scheduler.Yield();
                }
                receiver.IsCompleted = true;
                return(receiver);
            }
            else
            {
                return(null);
            }
        }
コード例 #2
0
ファイル: Channel.cs プロジェクト: zhaopan-vip/ZYSOCKET
        /// <summary>
        /// Receives a value over the channel. If no other <see cref="MicroThread"/> is sending data, the receiver will be blocked.
        /// If someone was sending data, which of the sender or receiver continues next depends on <see cref="Preference"/>.
        /// </summary>
        /// <returns>Awaitable data.</returns>
        public ChannelMicroThreadAwaiter <T> Get <T>()
        {
            Type key = typeof(T);


            if (!senders.ContainsKey(key) || (senders.ContainsKey(key) && senders[key].Count == 0))
            {
                var microThread = MicroThread.Current;
                if (microThread == null)
                {
                    throw new Exception("Cannot receive out of micro-thread context.");
                }

                var waitingMicroThread = ChannelMicroThreadAwaiter <T> .New(microThread);

                if (receivers.ContainsKey(key))
                {
                    receivers[key].Enqueue(waitingMicroThread);
                    return(waitingMicroThread);
                }
                else
                {
                    ConcurrentQueue <ChannelMicroThreadAwaiterBase> tmp = new ConcurrentQueue <ChannelMicroThreadAwaiterBase>();
                    receivers.AddOrUpdate(key, tmp, (a, b) => tmp);
                    receivers[key].Enqueue(waitingMicroThread);
                    return(waitingMicroThread);
                }
            }


            ChannelMicroThreadAwaiterBase sender;

            if (senders[key].TryDequeue(out sender))
            {
                if (Preference == ChannelPreference.PreferReceiver)
                {
                    sender.MicroThread.ScheduleContinuation(ScheduleMode.Last, sender.Continuation);
                }
                else if (Preference == ChannelPreference.PreferSender)
                {
                    sender.MicroThread.ScheduleContinuation(ScheduleMode.First, sender.Continuation);
                }
                sender.IsCompleted = true;
                return(sender as ChannelMicroThreadAwaiter <T>);
            }
            else
            {
                return(null);
            }
        }