Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
Channel.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.Threading.Tasks;
6 
7 namespace SiliconStudio.Core.MicroThreading
8 {
9  // TODO: Thread-safety
10  /// <summary>
11  /// Provides a communication mechanism between <see cref="MicroThread"/>.
12  /// </summary>
13  /// <remarks>
14  /// <see cref="MicroThread"/> can send and receive to a <see cref="Channel"/>. Depending on the <see cref="Channel.Preference"/>,
15  /// sending or receiving <see cref="MicroThread"/> might be suspended and yield execution to another <see cref="MicroThread"/>.
16  /// </remarks>
17  /// <typeparam name="T"></typeparam>
18  public class Channel<T>
19  {
20  Queue<ChannelMicroThreadAwaiter<T>> receivers = new Queue<ChannelMicroThreadAwaiter<T>>();
21  Queue<ChannelMicroThreadAwaiter<T>> senders = new Queue<ChannelMicroThreadAwaiter<T>>();
22 
23  public Channel()
24  {
25  Preference = ChannelPreference.PreferReceiver;
26  }
27 
28  /// <summary>
29  /// Gets or sets the preference, allowing you to customize how <see cref="Send"/> and <see cref="Receive"/> behave regarding scheduling.
30  /// </summary>
31  /// <value>
32  /// The preference.
33  /// </value>
34  public ChannelPreference Preference { get; set; }
35 
36  /// <summary>
37  /// Gets the balance, which is the number of <see cref="MicroThread"/> waiting to send (if greater than 0) or receive (if smaller than 0).
38  /// </summary>
39  /// <value>
40  /// The balance.
41  /// </value>
42  public int Balance { get { return senders.Count - receivers.Count; } }
43 
44  /// <summary>
45  /// Sends a value over the channel. If no other <see cref="MicroThread"/> is waiting for data, the sender will be blocked.
46  /// If someone was waiting for data, which of the sender or receiver continues next depends on <see cref="Preference"/>.
47  /// </summary>
48  /// <param name="data">The data.</param>
49  /// <returns>Awaitable data.</returns>
51  {
52  if (receivers.Count == 0)
53  {
54  // Nobody receiving, let's wait until something comes up
55  var microThread = MicroThread.Current;
56  var waitingMicroThread = ChannelMicroThreadAwaiter<T>.New(microThread);
57  waitingMicroThread.Result = data;
58  senders.Enqueue(waitingMicroThread);
59  return waitingMicroThread;
60  }
61 
62  var receiver = receivers.Dequeue();
63  receiver.Result = data;
64  if (Preference == ChannelPreference.PreferSender)
65  {
66  receiver.MicroThread.ScheduleContinuation(ScheduleMode.Last, receiver.Continuation);
67  }
68  else if (Preference == ChannelPreference.PreferReceiver)
69  {
70  receiver.MicroThread.ScheduleContinuation(ScheduleMode.First, receiver.Continuation);
71  throw new NotImplementedException();
72  //await Scheduler.Yield();
73  }
74  receiver.IsCompleted = true;
75  return receiver;
76  }
77 
78  /// <summary>
79  /// Receives a value over the channel. If no other <see cref="MicroThread"/> is sending data, the receiver will be blocked.
80  /// If someone was sending data, which of the sender or receiver continues next depends on <see cref="Preference"/>.
81  /// </summary>
82  /// <returns>Awaitable data.</returns>
84  {
85  if (senders.Count == 0)
86  {
87  var microThread = MicroThread.Current;
88  if (microThread == null)
89  throw new Exception("Cannot receive out of micro-thread context.");
90 
91  var waitingMicroThread = ChannelMicroThreadAwaiter<T>.New(microThread);
92  receivers.Enqueue(waitingMicroThread);
93  return waitingMicroThread;
94  }
95 
96  var sender = senders.Dequeue();
97  if (Preference == ChannelPreference.PreferReceiver)
98  {
99  sender.MicroThread.ScheduleContinuation(ScheduleMode.Last, sender.Continuation);
100  }
101  else if (Preference == ChannelPreference.PreferSender)
102  {
103  sender.MicroThread.ScheduleContinuation(ScheduleMode.First, sender.Continuation);
104  throw new NotImplementedException();
105  //await Scheduler.Yield();
106  }
107  sender.IsCompleted = true;
108  return sender;
109  }
110  }
111 }
ChannelMicroThreadAwaiter< T > Send(T data)
Sends a value over the channel. If no other MicroThread is waiting for data, the sender will be block...
Definition: Channel.cs:50
ChannelMicroThreadAwaiter< T > Receive()
Receives a value over the channel. If no other MicroThread is sending data, the receiver will be bloc...
Definition: Channel.cs:83