public bool Enqueue(int level, string msg) { var c = Encoding.UTF8.GetBytes(msg); var data = new byte[c.Length + HeaderSize]; var s = new MemoryStream(data); using (var sw = new BinaryWriter(s)) { sw.Write(level); // 4 sw.Write(DateTime.Now.Ticks); // 8 sw.Write(c.Length); // 4 sw.Write(c); } using (var stream = MMF.CreateViewStream()) { stream.Position = Front; if (IsFull) { // No space Log("No space for writing data"); return(false); } else { if (Front + data.Length < stream.Length) { // Enough space to go stream.Write(data, 0, data.Length); Front = stream.Position; Log("Enough space, enqueue data"); } else { // No enough space, break into two parts var firstLen = (int)(stream.Length - Front); var secondLen = data.Length - firstLen; stream.Write(data, 0, firstLen); stream.Position = ReservedSize; // reset to begin stream.Write(data, firstLen - 1, secondLen); Front = stream.Position; Log("Split data and enqueue"); } IsEmpty = false; } // 1. Front is catching up Rear in next cycle // 2. Front is near the end of the stream, and remaining data in the head is not enough if ((Rear > Front && Rear - Front < HeaderSize) || (stream.Length - Front - 1 + (Rear - ReservedSize)) < HeaderSize) { IsFull = true; } Log("Front:{0}, Rear:{1}", Front, Rear); return(true); } }
public SharedMessage Dequeue() { using (var stream = MMF.CreateViewStream()) { if (IsEmpty) { Log("No Data"); return(null); } else { using (var sr = new BinaryReader(stream)) { stream.Position = Rear; var header = new byte[HeaderSize]; if (stream.Length - Rear >= HeaderSize) { header = sr.ReadBytes(HeaderSize); } else { var firstLen = (int)(stream.Length - stream.Position); var secondLen = HeaderSize - firstLen; var header1 = sr.ReadBytes(firstLen); stream.Position = ReservedSize; var header2 = sr.ReadBytes(secondLen); Array.Copy(header1, header, firstLen); Array.Copy(header2, 0, header, firstLen - 1, secondLen); } var level = BitConverter.ToInt32(header, 0); var time = new DateTime(BitConverter.ToInt64(header, 4)); var len = BitConverter.ToInt32(header, 12); var msg = new byte[len]; if (stream.Position + len <= stream.Length) { msg = sr.ReadBytes(len); } else { var firstLen = (int)(stream.Length - stream.Position); var secondLen = len - firstLen; var msg1 = sr.ReadBytes(firstLen); stream.Position = ReservedSize; var msg2 = sr.ReadBytes(secondLen); Array.Copy(msg1, msg, firstLen); Array.Copy(msg2, 0, msg, firstLen - 1, secondLen); } Rear = stream.Position; IsFull = false; // 1. Rear is catching up Front // 2. Rear is near the end of the stream, the remaining data is not enough if (Front - Rear < HeaderSize || (stream.Length - Rear - 1 + (Front - ReservedSize)) < HeaderSize) { IsEmpty = true; } Log("Front:{0}, Rear:{1}", Front, Rear); var message = Encoding.UTF8.GetString(msg); Log("Level:{0}, Time:{1}, Message:{2}", level, time, message); return(new SharedMessage() { Level = level, Timestamp = time, Message = message }); } } } }