Introduction
I wanted to keep this article short and simple yet highlight all of things which everyone told us we wouldn't be able to do in C# but keep it short and still by the end of this article show them will be you will be able to do that and truly so much more.
The problem with understanding as I see it is that it stems from the precedent that prior knowledge stands alone in a sense like prior history it tends to repeat itself, however we as humans try to learn from our mistakes and correct them as we go. Without getting too much into evolution and and all that great stuff I just wanted to say fundamentally C# allows access to transistors which are the basis for all of the related functionality we achieve.
You can control everything about them including their state and you usually operate on them in 32 or 64 bit values at a time (even if you are only using 1 or 2 or 3 or 8 or 19 of ye given bits).
You can possibly also think about them like this if you wanted...
public enum QState
{
Uncertain,
Certain,
Transient,
On,
Off
}
This is always how I like to think of things because until quantum computers are in mainstream use this will be the acceptable real of thinking; this will should suffice as an acceptable way to represent them at the current time... on or off, even though transient state is also a possibility...
None the less...
What if you could have Generic Math support without building a delegate list?
What if you could have MultiBit types in C#?
What if you could INLINE some CIL right in a method?
What if you could access pointers in the same way as C++?
What if you could have support for Quantum Operations?
What if you did but just didn't know it?
Welcome to the future!
We will cover the solutions so some of the most sought after problems in a new and puzzling (for some) way which has always been right in front of our eyes but lacked the required vision to see it clearly for some reason. I will attempt to shed light on these aspects and make you all aware of this functionality!
We will solve basic copy cat style problems for people moving from C++ to C# to allow the Iterator concept to be utilized in C#
We will also then break down the Generic Math issue in a completely new integrated way which does not involve any Dictionary or delegate creation!
We will build a Complimentor a Storage Allocator and all of the associated classes such as Bit
, MultiBit
, Bitable
GarbadgeCollector
, ICoreObject
, GlobalObject32
, GlobablObject64
and much more!
Last but not least we will allow for INLINE Common Intermediate Language Support
right in any place anywhere in C# and best of all we will do this by the end of the article and everything will be working as intended with everything in total weighing in under 80k!
In part two of this article we talked about making things
easier, Welcome to part III.
Engineering is as Engineering Does, this is typical when you
see jQuery this everywhere, async this and Begin that. What it means is (in short) is that most developers are monkey see, monkey do!
They see example x they follow example x as closely as possible
and choose not to deviate and thus as a result we are left with the same
technology 20 years ago that we have today.
Thank the stars there are people who are innovating and genuine attempts are being made to do things easier and don’t just use jQuery (which I hate) and because it’s cool or
the fad. They don’t use @this or # that. They have their own way of thinking
and it may not be in line with how everyone else thinks... yet but sometimes it
catches on and blows up and we start the cycle all over again.
One example of which I can immediately come up with is the guys
over @ the Reactive Extensions Project!
I would have rather seen a polished version of
this integrated into the Framework then the async keyword but I guess the UI folks have won
again!
After all it’s them who have to sort through the tons of
records in our databases, and all the other fun things no one will ever see or
know or care about until something goes wrong, at which point the helpless guy
who wrote the software gets a mouthful and hopefully can restrain from going
*ape $h17 * and shooting up his local library....
It is like people only care about what they see on computers... Well not me and not a lot of you...
Nonetheless I digress, It is however a fact that some of the
most mundane work topics stem from not being able to use the LINQ classes provided
for a number of reasons.
- State - You don’t have any state with LINQ, things happen in
a linear fashion and usually once the enumeration is started you have the whole
kitten caboodle to deal with.
- Allocation - Therefore you cannot really use a LINQ set
efficiently without Projecting it! This means you have to call
ToArray
in most
cases since iterating a set 1 by 1 when there are 10 of thousands if not more is probably not the
best way.
You also can’t set the current member!
Enter Iterators..
Iterators are IEnumerable
and IEnumerator
, they control their
own state and give rise to some interesting concepts such as EnumerableSegment
which allows for offset operations on any IEnumerable
. For example say you
wanted to do "for(i= 2; i < 10 - 2; ++i) action()
" With an enumerable you
can just Skip and Take but what if you wanted a way to control where the
Skipping started when someone used Skip? What if you had 10 different
enumerables and you wanted to make them look like a single enumerable to the
observer? then this is where that class can help.
It supports C++ style patterns such as setting the Current item
(with associated events
) and other events for PreIncrement
, PostIncrement
,
SiblingIncrement
, etc..
#region Iterators
public class Iterator<T> :
EnumerableSegment<T>,
Iterator
{
#region Properties
public DateTime Started { get; internal protected set; }
public DateTime Ended { get; internal protected set; }
public Iterator Parent { get; protected set; }
public IEnumerable<T> Enumerable { get; protected set; }
public IEnumerator<T> Enumerator { get; protected set; }
#endregion
#region Overrides
public override T Current
{
get
{
Exception ex = null;
try
{
try { OnCurrentRead(); }
catch (Exception _) { ex = _; }
return base.Current;
}
finally { if (ex != null) throw ex; }
}
internal protected set
{
try { base.t = value; }
finally { CurrentAssigned(this); }
}
}
public override bool MoveNext()
{
bool error = false;
try
{
if (Index == -1) OnBegin();
try { OnPreIncrement(); }
catch { error = true; }
finally { error = error || !base.MoveNext(); }
IEnumerator<T> enumerator = Enumerator;
error = !enumerator.MoveNext();
if (!error) Current = (T)enumerator.Current;
return !error;
}
finally { OnPostIncrement(); if (error || Index > VirtualCount) OnEnd(); }
}
#endregion
#region Constructor
public Iterator() : base() { AssignEvents(this); }
public Iterator(IEnumerable<T> enumerable) : base(enumerable) { AssignEvents(this); Enumerable = enumerable; Enumerator = Enumerable.GetEnumerator(); }
public Iterator(IEnumerable<T> enumerable, int index, int count) : base(enumerable, index, count) { AssignEvents(this); Enumerable = enumerable; Enumerator = Enumerable.GetEnumerator(); }
static void AssignEvents(Iterator<T> iterator)
{
iterator.PostDecrement += IteratorPostDecrement;
iterator.PostIncrement += IteratorPostIncrement;
iterator.PreIncrement += IteratorPreIncrement;
iterator.PreDecrement += IteratorPreDecrement;
iterator.CurrentAssigned += IteratorCurrentAssigned;
iterator.CurrentRead += IteratorCurrentRead;
iterator.Begin += IteratorBegin;
iterator.End += IteratorEnd;
}
static void IteratorEnd(Iterator sender)
{
(sender as Iterator<T>).Ended = DateTime.UtcNow;
}
static void IteratorBegin(Iterator sender)
{
(sender as Iterator<T>).Started = DateTime.UtcNow;
}
static void IteratorPostIncrement(Iterator sender)
{
}
static void IteratorCurrentRead(Iterator sender)
{
}
static void IteratorCurrentAssigned(Iterator sender)
{
}
static void IteratorPreIncrement(Iterator sender)
{
}
static void IteratorPreDecrement(Iterator sender)
{
}
static void IteratorPostDecrement(Iterator sender)
{
}
static void IteratorPostIncrment(Iterator sender)
{
}
#endregion
#region Iterator
public static Iterator operator +(Iterator<T> it, Iterator<T> that)
{
return (it as IEnumerable<T>).Concat(that) as Iterator;
}
public static Iterator operator -(Iterator<T> it, Iterator<T> that)
{
return (it as IEnumerable<T>).Skip(that.Count) as Iterator;
}
int Iterator.VirtualCount
{
get { return base.VirtualCount; }
}
int Iterator.VirtualIndex
{
get { return base.VirtualIndex; }
}
int Iterator.CurrentIndex
{
get
{
return base.Index;
}
set
{
if (value < 0) base.Reset();
base.Index = value;
}
}
public void SetCurrent(T current) { base.Current = current; }
public T GetCurrent(T current) { return base.Current; }
#endregion
#region Events
internal void OnBegin()
{
Begin(this);
}
internal void OnEnd()
{
End(this);
}
internal void OnPreIncrement()
{
PreIncrement(this);
}
internal protected void OnPostIncrement()
{
PostIncrement(this);
}
internal void OnPreDecrement()
{
PreDecrement(this);
}
internal protected void OnPostDecrement()
{
PostDecrement(this);
}
internal protected void OnSiblingIncrement()
{
SiblingIncrement(this);
}
internal protected void OnSiblingDecrement()
{
SiblingDecrement(this);
}
internal protected void OnCurrentRead()
{
CurrentRead(this);
}
internal protected void OnCurrentAssigned()
{
CurrentAssigned(this);
}
public event IterationHanlder PreIncrement;
public event IterationHanlder PreDecrement;
public event IterationHanlder PostIncrement;
public event IterationHanlder PostDecrement;
public event IterationHanlder SiblingIncrement;
public event IterationHanlder SiblingDecrement;
public event IterationHanlder CurrentRead;
public event IterationHanlder CurrentAssigned;
public event IterationHanlder Begin;
public event IterationHanlder End;
#endregion
#region IEnumerator
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this;
}
object System.Collections.IEnumerator.Current
{
get { return (this as Iterator<T>).Current; }
}
bool System.Collections.IEnumerator.MoveNext()
{
return (this as Iterator<T>).MoveNext();
}
void System.Collections.IEnumerator.Reset()
{
(this as Iterator<T>).Reset();
}
#endregion
#region Statics
public static void ForAll()
{
}
public static bool Any()
{
return false;
}
#endregion
}
public delegate void IterationHanlder(Iterator sender);
public interface Iterator : System.Collections.IEnumerable, System.Collections.IEnumerator, IDisposable
{
event IterationHanlder Begin;
event IterationHanlder End;
int VirtualCount { get; }
int VirtualIndex { get; }
int CurrentIndex { get; set; }
event IterationHanlder PreIncrement;
event IterationHanlder PreDecrement;
event IterationHanlder PostIncrement;
event IterationHanlder PostDecrement;
event IterationHanlder SiblingIncrement;
event IterationHanlder SiblingDecrement;
event IterationHanlder CurrentRead;
event IterationHanlder CurrentAssigned;
}
#endregion
In short, it’s main purpose was to do away with petty memory allocations
which caused paging when performed frequently. This can also be solved using a "ScratchTable
' pattern where you only take note of the index in where things are being changed but the above was more natural to implement for the example without giving too much away " />
Say you wanted to insert a byte into a stream, well you might say "can't you just write the byte to the stream then?" Well what if you wanted the stream to
remain untouched? This way a Save method would be able to take all changes and
integrate them into a Stream when you decided and without paging or allocating anything more then what was required and only one time?
This is where the EnumerableByteStream
helps... it saves those
allocations for any IEnumerable<byte>
you want to put into a stream and then
when you enumerate the stream you only enumerate the stream up to the position
it was written in, reading past that point you are actually just enumerating
the yielded Enumerable bytes which have been queued in memory with the embedded use of
the IEnumerator
interface...
#region EnumerableByteStream
public class EnumerableByteStream : EnumerableSegment<byte>, IEnumerable<byte>, IEnumerator<byte>, IList<byte>
{
protected int m_Current;
internal protected System.IO.Stream m_Stream;
internal protected bool m_Disposed;
internal EnumerableByteStream m_Self;
bool Initialized { get { return CurrentInt != -1; } }
public int CurrentInt { get { return Current; } }
public EnumerableByteStream(byte Byte) : this(Byte.Yield()) { }
public EnumerableByteStream(IEnumerable<byte> bytes, int? index = null, int? count = null)
: base(bytes, index ?? 0, (int)(count.HasValue ? count - index : -1)) { }
public EnumerableByteStream(System.IO.Stream stream, int? index = null, int? count = null)
: this(null as IEnumerable<byte>, index ?? (int)stream.Position, count ?? (int)stream.Length)
{
m_Stream = stream;
m_Current = Current;
}
public IEnumerable<byte> ToArray(int offset, int count, byte[] buffer)
{
if (offset < 0) throw new ArgumentOutOfRangeException("offset must refer to a location within the buffer.");
else if (count + offset > Length) throw new ArgumentOutOfRangeException("count must refer to a location within the buffer with respect to offset.");
if (count == 0) return Enumerable.Empty<byte>();
buffer = buffer ?? new byte[count];
int len = count;
while ((len -= m_Stream.Read(buffer, offset, count)) > 0
&&
Remaining > 0)
{
}
return buffer;
}
public IEnumerator<byte> GetEnumerator()
{
if (CurrentInt == -1) MoveNext();
while (!m_Disposed && MoveNext()) yield return Current = (byte)m_Current;
}
public override bool MoveNext()
{
if (base.MoveNext()) return CoreGetEnumerator() != -1;
return false;
}
int CoreGetEnumerator(long direction = 1)
{
if (!m_Disposed && m_Stream.Position < Count) return Current = (byte)(m_Current = m_Stream.ReadByte());
else unchecked { return Current = (byte)(m_Current = -1); }
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
internal protected long CoreIndexOf(IEnumerable<byte> items, int start = -1, int count = -1)
{
if (m_Stream == null || m_Disposed || items == null || items == Enumerable.Empty<byte>() || count == 0) return -1;
if (count == -1) count = items.Count();
if (!Initialized && !MoveNext()) return -1;
if (start != -1 && start + count > Count) return -1;
else if (start != -1 && start != Position) if (m_Stream.CanSeek) m_Stream.Seek(start, System.IO.SeekOrigin.Begin);
else return -1;
using (IEnumerator<byte> itemPointer = items.Skip(start).Take(count).GetEnumerator())
{
if (!itemPointer.MoveNext()) return -1;
long position = Position;
if (start == -1 && m_Stream.CanSeek && m_Stream.Position != 0 && itemPointer.Current != Current)
{
Reset();
}
else start = (int)m_Stream.Position;
while (itemPointer != null)
{
int j = count;
while (itemPointer.Current == Current && (--j > 0))
{
if (!itemPointer.MoveNext()) break;
}
if (j == 0)
{
return m_Stream.Position - 1;
}
if (!MoveNext()) break;
}
if (start == -1 && m_Stream.CanSeek && position != Position) m_Stream.Seek(position, System.IO.SeekOrigin.Begin);
return -1;
}
}
internal protected int CoreIndexOf(byte item, int start, int count) { return (int)CoreIndexOf(item.Yield(), start, count); }
public virtual int IndexOf(byte item)
{
return CoreIndexOf(item, -1, 1);
}
public virtual void Insert(int index, byte item)
{
EnumerableByteStream newPointer = new EnumerableByteStream((new EnumerableByteStream(m_Stream, 0, index - 1) as IEnumerable<byte>).
Concat(item.Yield()).
Concat(new EnumerableByteStream(m_Stream, index - 1, Count - index + 1) as IEnumerable<byte>));
m_Self = newPointer;
}
public virtual void RemoveAt(int index)
{
m_Stream = LinkedStream.LinkAll(new EnumerableByteStream(m_Stream, 0, index), new EnumerableByteStream(m_Stream, ++index, Count - index));
}
public virtual byte this[int index]
{
get
{
if (index < 1) index = 0;
if (index != m_Stream.Position)
{
if (m_Stream.CanSeek) m_Stream.Seek(index, System.IO.SeekOrigin.Begin);
else throw new InvalidOperationException("You can only move the index if the underlying stream CanSeek");
}
return (byte)m_Stream.ReadByte();
}
set
{
if (m_Stream.CanWrite && m_Stream.CanSeek) m_Stream.Seek(index, System.IO.SeekOrigin.Begin);
else throw new InvalidOperationException("You can logically set a byte in the stream the index if the underlying stream supports CanWrite and CanSeek");
m_Stream.Write(value.Yield().ToArray(), 0, 1);
}
}
public virtual void Add(byte item)
{
if (m_Stream.CanWrite) m_Stream.Write(item.Yield().ToArray(), 0, 1);
else throw new InvalidOperationException("You can logically set a byte in the stream the index if the underlying stream supports CanWrite");
}
public virtual void Clear()
{
m_Stream = new System.IO.MemoryStream();
return;
}
public virtual bool Contains(byte item)
{
return CoreIndexOf(item, 0, 1) != -1;
}
public virtual void CopyTo(byte[] array, int arrayIndex)
{
CoreCopyTo(array, arrayIndex);
}
public virtual void CopyTo(System.IO.Stream stream, int? bufferSize = null)
{
m_Stream.CopyTo(stream, (int)(stream.Length - stream.Position));
}
public virtual void CoreCopyTo(byte[] array, int arrayIndex, int length = -1)
{
if (length <= 0) return;
if (length == -1) length = array.Length - arrayIndex;
else if (length > m_Stream.Length) throw new ArgumentOutOfRangeException("Can't copy more bytes then are availble from the stream");
m_Stream.Read(array, arrayIndex, length);
}
public long Position { get { return Index; } }
public virtual long Length
{
get { return Count; }
}
public virtual bool IsReadOnly
{
get { return m_Stream.CanWrite; }
}
public virtual bool Remove(byte item)
{
return false;
}
public static implicit operator System.IO.Stream(EnumerableByteStream eByteStream) { return eByteStream.m_Stream; }
object System.Collections.IEnumerator.Current
{
get { return GetEnumerator().Current; }
}
public override void Reset()
{
m_Current = -1;
if (m_Stream.CanSeek) m_Stream.Seek(VirtualIndex, System.IO.SeekOrigin.Begin);
base.Reset();
}
public long Seek(long offset, System.IO.SeekOrigin origin) { if (m_Stream.CanSeek) return m_Stream.Seek(offset, origin); return m_Stream.Position; }
}
#endregion
It’s kind of confusing in the end and thus why I implemented the
Iterator
pattern... but in the end I am not too sure they are any more useful
than anything else which was already provided in the language, and on top of
that it kind of resembles Java which I hate with a passion.
On a side note the ArraySegmentList
is especially useful for dealing with
large sets of data and also when used with SocketAsyncEventArg
’s as the
BufferList
property.
Please make sure you build the ArraySegmentList
before assigning it to
the SocketAsyncEventArg
’s instance because once assigned the
SocketAsyncEventArg
’s instance will prevent further modification by exposing
the SocketAsyncEventArg
’s BufferList
as IList
which internally has been
implemented as a ReadOnlyCollection
to prevent modification.
There will be complete MediaSocketPool
implementation released in the coming weeks along with a more mature version of this library @ Managed Media Aggregation
Now ...
This hopefully makes things easier but what if we tackled
real problems like the Generic Math problem?
That thing has been beat to death 1000 times over but I think I
might have something new and interesting but before we get to that...
Since learned have we a reliable method of achieving Microsecond precision what would be next?
#region Cross Platform μTimer
public sealed class μTimer : IDisposable
{
#region Not Applicable for the MicroFramework
#if(!MF)
#region Uncesessary Interop (Left for Comparison)
#if MONO
using System.Runtime.<wbr />InteropServices;
[System.Runtime.<wbr />InteropServices.DllImport("<wbr />libc.so")]
static extern int usleep (uint amount);
void uSleep(int waitTime) { usleep(waitTime); }
#else
[System.Runtime.<wbr />InteropServices.DllImport("<wbr />Kernel32.dll")]
static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
[System.Runtime.<wbr />InteropServices.DllImport("<wbr />Kernel32.dll")]
static extern bool QueryPerformanceFrequency(out long lpFrequency);
public static void uSleep(TimeSpan amount) { μTimer.uSleep(((int)(amount.<wbr />TotalMilliseconds * 1000))); }
public static void uSleep(int waitTime)
{
long time1 = 0, time2 = 0, freq = 0;
QueryPerformanceCounter(out time1);
QueryPerformanceFrequency(out freq);
do
{
QueryPerformanceCounter(out time2);
} while ((time2 - time1) < waitTime);
}
#endif
#endregion
#endif
#endregion
#region Statics
const ushort Port = 7777;
public const long TicksPerMicrosecond = TicksPerNanoSecond / 10;
public const long TicksPerNanoSecond = TimeSpan.TicksPerMillisecond / 100;
public const long Divider = TimeSpan.TicksPerSecond / TimeSpan.TicksPerMillisecond;
static bool m_Disposed;
static Socket m_Socket = new Socket(AddressFamily.<wbr />InterNetwork, SocketType.Stream, ProtocolType.Tcp);
static SocketAsyncEventArgs m_SocketMemory = new SocketAsyncEventArgs();
public static DateTime LocalTime { get { return new DateTime(Environment.TickCount * TimeSpan.TicksPerMillisecond); } }
public static DateTime UniversalTime { get { return LocalTime.ToUniversalTime(); } }
public static DateTime RealTimeLocal
{
get
{
DateTime now = LocalTime;
Media.Common.μTimer.μSleep(<wbr />TimeSpan.FromTicks((TimeSpan.<wbr />TicksPerMillisecond / Media.Common.μTimer.<wbr />TicksPerMicrosecond / Media.Common.μTimer.Divider)))<wbr />;
DateTime then = DateTime.Now;
return now + (then - now);
}
}
public static DateTime RealTimeUniversal
{
get
{
return RealTimeLocal.ToUniversalTime(<wbr />);
}
}
static μTimer()
{
try
{
m_Socket.Bind(new System.Net.IPEndPoint(System.<wbr />Net.IPAddress.Loopback, Port));
m_Socket.Listen(1);
m_SocketMemory.Completed += BeginProcess;
#if(!MF)
if (!m_Socket.AcceptAsync(m_<wbr />SocketMemory))
{
BeginProcess(typeof(μTimer), m_SocketMemory);
}
#else
new Thread(()=> BeginProcess(this, null)).Start();
#endif
}
catch
{
throw;
}
}
#if(!MF)
static void BeginProcess(object sender, SocketAsyncEventArgs e)
{
#else
static void BeginProcess(object sender, object args e)
{
while(!m_Disposed)
{
try
{
Socket dontCare = m_Socket.Accept(); dontCare.Dispose();
throw new System.<wbr />InvalidProgramException("A Connection to the system was made by a unauthorized means.");
}
catch { throw; }
}
#endif
if (!m_Disposed && e.LastOperation == SocketAsyncOperation.Connect)
{
try
{
throw new System.<wbr />InvalidProgramException("A Connection to the system was made by a unauthorized means.");
}
finally
{
if (e.AcceptSocket != null) e.AcceptSocket.Dispose();
}
}
}
public static void μSleep(TimeSpan amount)
{
DateTime now = μTimer.UniversalTime, then = μTimer.UniversalTime;
TimeSpan waited = now - then;
if (waited > amount) return;
else System.Threading.Thread.Sleep(<wbr />amount - waited);
waited = now - then;
if (waited > amount) return;
else unchecked
{
if (m_Socket.WaitRead(((int)((<wbr />amount.Ticks - waited.Ticks / TicksPerMicrosecond) / Divider))))
{
then = μTimer.UniversalTime;
amount -= waited;
waited = now - then;
if (waited > amount) return;
else System.Threading.Thread.Sleep(<wbr />amount - waited);
}
}
}
public static void μSleep(int amount) { μTimer.μSleep(TimeSpan.<wbr />FromMilliseconds(amount * TimeSpan.TicksPerMillisecond))<wbr />; }
#endregion
void IDisposable.Dispose()
{
m_Disposed = true;
if (m_Socket != null)
{
m_Socket.Dispose();
m_Socket = null;
}
}
}
#endregion
Well since you can now make a real time clock using C# alone
and my MicroTimer
the next steps for that would be to create a SocketPrecisionWaitHandle
. (Again not everything for free)
It would derive from WaitHandle
and expose Microsecond
precision overloads.
It would have the added benefit that Wait and Set operations
were actually happening on System Interrupts and allow you to signal other
threads with the same scheduling precision as the μTimer
class.
It will use the MultiCastLoopBack
adapter by default for the
best performance.
There could be a Tcp and Udp version although I suspect RAW
Sockets would provide the best performance and allow for the most flexibility
when sending data through the WaitHandles
with the new
SocketPrecision.PostMessage
API’s which allow you to send your messages to all
SocketWaitHandles
or just a single known SocketWaitHandle
.
It is essentially a SocketServer
which only sends data on the
local host.
When you create a SocketPrecisionWaitHandle
you connect to the
SocketPrecisionHost
and then all WaitOne
commands will be performed on the
Socket.
Default signaling commands will just send an empty packet of 0
bytes however in advanced cases you can send data up to a certain length long
depending on the SocketPrecisionHost
’s allowances.
In short this gives you the developer the ability to schedule
interprocess communication safely , efficiently and without the need for
special kernel mode drivers.
If you need encryption from other prying eyes then you can use
TCP and a SSL Stream or another form when you derive the SocketPrecisionHost
into a SecureSocketPrecisionHost
and Client combination.
I would recommend only using empty transfers and single bytes
as Operation Codes since null 0 - 255 (256 total) values should be sufficient
to support most scenarios.
ets see how to layout a Flagged byte using all 256 possible states! (null included)
[Flags]
public enum MediaChannelBindingState : byte
{
Unitialized = 0, BeforeInitialized = 1, Initialized = 2,
AfterInitialized = 3, Reserved = 4, BeforeConnected = 5,
ReservedConnected = 6, ReservedPending = 7,
ReservedCompleted = 8,
Connected = 9,
AfterConnected = 10,
BeforeQueueData = 15, QueueData = 16, AfterQueueData = 17, BeforeSendData = 31,
SendData = 32, AfterSendData = 33,
ReservedBeforeReceiveData = 59,
BeforeReceiveData = 60,
ReceiveData = 61, ReceiveReserved = 62,
AfterReceiveData = 63,
ReservedAfterReceiveData = 64,
BeforeProcessData = 65,
ProcessingData = 66,
BeforeReservedDisconnect = 127,
ReservedDisconnect = 128,
BeforeDisconnected = 129,
Disconnected = 129,
AfterDisconnected = 130,
ReservedAfterDisconnected = 131,
Invalid = byte.MaxValue
}
The PostMessage
is different from the Set and WaitOne
API in
the sense it specifically allows for larger sets of data on dedicated Pool’s
when those resources are required e.g. for processing or calculation and
subsequent callback.
Lets get back to the Generic Math Problem...
Generics and Math have long history of problems mostly due to
how the C# compiler internally handles mathematical operations when generics
are used.
This results in a developer usually having to take many steps
such a building a delegate dynamically when required to perform a calculation
on a generic type say
<T> = decimal and <U> = double inter alia.
CIL Has no problem with this, but it's the various Compilers e.g. VB.Net or C# however...
This brings me to another problem, the inability in C# to
define Binary properly, yes StructLayout
helps a great deal and without it I am
not sure how I would have achieved so much already however I aim to take that much further with the following types:
Enter Bits, Bitable and Number and Much much more...
They are what I hope will be the next way of thinking about
managed types, as you will see they support unmanaged and managed style code
with the same API. They allow unprecedented control over the binary aspects of
types. (It could be separated and hidden and only shown under different interfaces but I like the current approach)
You will see everything has an interface to abstract away virtual call overhead in .NET.
This could be implemented just about anywhere and in any language but I have chosen C# because I wanted to display my skill with and love for the language.
ICoreUnit
- This represents the core units of energy the Framework is able to work with, right now only Transistor is implemented but in the future Qubit's could be easily implemented using this Framework with minor adjustments.
There is even a QuBit
and QuByte
implementation inside...
#region Quantum
public abstract class QuBit : IComparable<MultiBit>
{
public bool[] States { get; internal protected set; }
public System.Numerics.Complex Entanglement { get; set; }
public abstract int CompareTo(MultiBit other);
}it
public abstract class QuByte : IComparable<Bitable>
{
public abstract IEnumerable<QuBit> QuBits { get; internal protected set; }
public abstract int CompareTo(Bitable other);
}
#endregion
Transistor
- Implements a implicit boolean conversion to traditional C style language. In the future I imagine that this will be something else with many sates (e.g. a QuBit) -
Bit
- Implements the of a single ICoreUnit of energy in Today's computers. -
MultiBit
- Derives from Bit. Implements the use of Multi ICoreUnits of energy. It keeps the first bit and stores Bits1_N enumerable revealing the underlying count.
-
CommonIntermediaLanguage
- A class which enables the use of Common Intermediate Language inline. -
IManipulator
- This represents the Hardware manipulations which occur. Since I didn't have time to make everything the way I wanted this class is static and I use the IManipulator
Interface which could and probably should also Implement a IHardware Interface...Since the default number complimenting system is already two's compliments I have decided to also leave this concept blank for artists of the future.
-
StorageAllocator
- Just a reference allocator which takes memory from the System.
-
GarbadgeCollector
- Just a class to keep the allocator and the allocations which occur along with their references.There should also eventually be a RunTime class which keeps the reference count.You will find support for 32 and 64 bit objects and the ability to convert them.
There should also eventually be a way to copy a .NET
object
into a Bitable
but that should be easy to add if you know what you are doing.
From there the rest is left up to your imagination! Everything works as is and if there are any questions I would happy to answer!
There is also a lot more then can do for computer science in general
such as allow easier enumeration of underlying memory systems but I am off on
another tangent so before I forget what I am writing about here we go:
Bits are ValueTypes
and Bitable’s
are classes (ReferenceTypes
) which have more
Bits
in them.
Here are the classes as I describe each one.
Bits
- A Representation of binary data. Bits don’t know what
Endian they are stored in nor do they care (nor should they because of their relative electrical nature, Endianess is only a thing we enforce on the system, it technically doesn't exist). They can be accessed in pointer
notation e.g. "data[0]" or using the static object oriented methods GetBit
,
SetBit
, CheckBit
, ToggleBit
. Bits are always 1 Byte in size and have no
additional properties or overhead. They are specially laid out structures.Each
Bits type supports Unsafe pointers as well as "Safe pointers"
#region Bits
[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit,
Size = 1,
Pack = 0,
CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public struct Bits : System.Collections.IEnumerable, IEnumerable<bool>
{
public const int Size = 1;
public const int BitSize = 8;
[System.Runtime.InteropServices.FieldOffset(0)]
internal byte m_Bits;
unsafe byte* UnsafeBits
{
get
{
fixed (byte* memory = &m_Bits)
{
return memory;
}
}
}
public byte ManagedBits { get { return m_Bits; } }
public Bits(byte b) { m_Bits = b; }
public override bool Equals(object obj)
{
if (obj is Bits)
{
Bits unboxed = (Bits)obj;
if (unboxed != null) return unboxed == this;
else return false;
}
else return base.Equals(obj);
}
public override int GetHashCode()
{
return m_Bits.GetHashCode();
}
public bool this[int index]
{
get { return GetBit(this, index); }
set { SetBit(this, index); }
}
public static bool GetBit(Bits b, int index)
{
return (b.m_Bits & (Size << index)) > 0;
}
public static void SetBit(Bits b, int index)
{
b |= (Size << index);
}
public static void ClearBit(Bits b, int index)
{
b &= ~(Size << index);
}
public static void Toggle(Bits b, int index)
{
b ^= (byte)(Size << index);
}
public static implicit operator byte(Bits b) { return b.m_Bits; }
public static implicit operator int(Bits b) { return b.m_Bits; }
public static implicit operator Bits(byte b) { return new Bits(b); }
public static Bits operator ^(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits ^ amount));
}
public static Bits operator |(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits | amount));
}
public static Bits operator &(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits & amount));
}
public static bool operator >(Bits b, int amount)
{
return b.m_Bits > amount;
}
public static bool operator <(Bits b, int amount)
{
return b.m_Bits > amount;
}
public static Bits operator >>(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits >> amount));
}
public static Bits operator <<(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits << amount));
}
public static Bits operator +(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits + amount));
}
public static Bits operator -(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits - amount));
}
public static Bits operator *(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits * amount));
}
public static Bits operator /(Bits b, int amount)
{
return new Bits((byte)(b.m_Bits / amount));
}
public static Bits operator ^(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits ^ other.m_Bits));
}
public static Bits operator |(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits | other.m_Bits));
}
public static Bits operator &(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits & other.m_Bits));
}
public static bool operator >(Bits b, Bits other)
{
return b.m_Bits > other.m_Bits;
}
public static bool operator <(Bits b, Bits other)
{
return b.m_Bits > other.m_Bits;
}
public static Bits operator +(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits + other.m_Bits));
}
public static Bits operator -(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits - other.m_Bits));
}
public static Bits operator *(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits * other.m_Bits));
}
public static Bits operator /(Bits b, Bits other)
{
return new Bits((byte)(b.m_Bits / other.m_Bits));
}
public static bool operator ==(Bits b, int a) { return a == b.m_Bits; }
public static bool operator !=(Bits b, int a) { return !(a == b.m_Bits); }
public static bool operator ==(Bits b, byte a) { return a == b.m_Bits; }
public static bool operator !=(Bits b, byte a) { return !(a == b.m_Bits); }
public static bool operator ==(Bits b, Bits a)
{
return a.m_Bits == b.m_Bits;
}
public static bool operator !=(Bits b, Bits a)
{
return !(a == b);
}
public System.Collections.IEnumerator GetEnumerator()
{
return new BitsEnumerator(this);
}
IEnumerator<bool> IEnumerable<bool>.GetEnumerator()
{
return new BitsEnumerator(this);
}
}
#endregion
Bitable - A Representation of binary data which is Endian
aware, it’s size it at 1 Byte but can be any number of Bytes which the system
can support. Each Bitable type supports Unsafe pointers as well as "Safe
pointers"
#region Bitable
public class Bitable : IEnumerable<Bits>, IEnumerable<byte> , IEnumerable<bool>
{
#region Statics
public static Endian SystemEndian = System.BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian;
public readonly static Bitable SingleZero = new Bitable((Single)0);
public readonly static Bitable ByteZero = new Bitable((byte)0);
public readonly static Bitable ShortZero = new Bitable((short)0);
public readonly static Bitable IntZero = new Bitable(0);
public readonly static Bitable LongZero = new Bitable(0L);
public readonly static Bitable DoubleZero = new Bitable(0.0D);
public readonly static Bitable DecimalZero = new Bitable(0.0M);
public readonly static Bitable Null = new Bitable(SystemEndian);
#endregion
#region Properties
unsafe byte* UnmanagedBytes
{
get
{
fixed (byte* memory = Memory)
{
return memory;
}
}
}
public Endian Endian { get; protected set; }
public int Count { get { return Memory.Length; } }
public int BitCount { get { return Count * 8; } }
public byte this[int index]
{
get
{
return Memory[index];
}
set
{
Memory[index] = value;
}
}
#endregion
#region Fields
internal byte[] Memory;
#endregion
#region Constructors
public Bitable(Bitable other)
{
if (other.Memory != null)
{
Memory = new byte[other.Count];
other.Memory.CopyTo(Memory, 0);
}
Endian = other.Endian;
}
public Bitable(Bits bits, Endian endian = Common.Bits.Endian.Unknown)
{
Memory = new byte[1];
Memory[0] = bits.m_Bits;
Endian = endian;
}
internal Bitable(Endian? endian = null)
{
Endian = endian ?? (System.BitConverter.IsLittleEndian ? Endian.LittleEndian : Endian.BigEndian);
}
public Bitable(bool Boolean)
: this((byte)(Boolean ? 1 : 0)) { }
public Bitable(byte Byte, Endian? endian = null)
: this(endian)
{
Memory = new byte[] { Byte };
}
public Bitable(sbyte SByte, Endian? endian = null)
: this(endian)
{
Memory = new byte[] { (byte)SByte };
}
public Bitable(Int16 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(UInt16 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(Int32 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(UInt32 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(Int64 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(UInt64 Int, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Int);
}
public Bitable(Single Single, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Single);
}
public Bitable(Double Double, Endian? endian = null)
: this(endian)
{
Memory = BitConverter.GetBytes(Double);
}
public Bitable(Decimal Decimal, Endian? endian = null)
: this(endian)
{
Memory = System.Decimal.GetBits(Decimal).Select(a => BitConverter.GetBytes(a)).SelectMany(b => b).ToArray();
}
#endregion
IManipulator
- The default interface which defines the
implementation specifics about bit manipulation within a Bitable
.
Manipulator
- A static class which represents common operations
in computer science e.g. ShiftLeft, ShiftRight, Add, Substract etc.
These classes should have been abstracted against a IHardware
interface for a better design but again I didn't want to give everything away! See my notes in the bottom "Interesting Points
"
#region Manipulator
public sealed class Manipulator : IManipulator
{
public delegate Bitable Manipulation(Bitable a, Bitable b);
public delegate void ReferenceManipulation(ref Bitable a, ref Bitable b);
public delegate bool Evaluation(Bitable a, Bitable b);
public delegate bool ReferenceEvaluation(ref Bitable a, ref Bitable b);
public delegate void Operation(Bitable a, Bitable b);
public delegate void ReferenceOperation(ref Bitable a, ref Bitable b);
public static void Prepare(ref Bitable a, ref Bitable b)
{
if (b > a)
{
Bitable temp = b;
b = a;
a = temp;
}
}
public static Bitable Manipulate(Bitable a, Bitable b, Manipulation manipulation)
{
return manipulation(a, b);
}
public static void Manipulate(ref Bitable a, ref Bitable b, ReferenceManipulation referenceManipulation)
{
referenceManipulation(ref a, ref b);
}
public static void Addition(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] += b[i];
}
public static Bitable Add(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Addition(ref result, ref b);
return result;
}
public static void Subtraction(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] -= b[i];
}
public static Bitable Subtract(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Subtraction(ref result, ref b);
return result;
}
public static void Multiplication(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] *= b[i];
}
public static Bitable Multiply(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Multiplication(ref result, ref b);
return result;
}
public static void Division(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] /= b[i];
}
public static Bitable Divide(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Division(ref result, ref b);
return result;
}
public static void Modulo(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] %= b[i];
}
public static Bitable Modulus(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
Modulo(ref result, ref b);
return result;
}
public static bool GreaterThan(Bitable a, Bitable b)
{
return a.Count > b.Count;
}
public static bool LessThan(Bitable a, Bitable b)
{
return a < b;
}
public static void OR(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] |= b[i];
}
public static Bitable OR(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
OR(ref result, ref b);
return result;
}
public static void XOR(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] ^= b[i];
}
public static Bitable XOR(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
XOR(ref result, ref b);
return result;
}
public static void AND(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] &= b[i];
}
public static Bitable AND(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
AND(ref result, ref b);
return result;
}
public static void NOT(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] = (byte)~b[i];
}
public static Bitable NOT(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
NOT(ref result, ref b);
return result;
}
public static void NAND(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] &= (byte)(~b[i]);
}
public static Bitable NAND(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
NAND(ref result, ref b);
return result;
}
public static void NOR(ref Bitable a, ref Bitable b)
{
for (int i = 0; i < Math.Min(a.Count, b.Count); ++i)
a[i] |= (byte)(~b[i]);
}
public static Bitable NOR(Bitable a, Bitable b)
{
Prepare(ref a, ref b);
Bitable result = new Bitable(a);
NOR(ref result, ref b);
return result;
}
public static void ShiftLeft(ref Bitable a, ref int amount, ref int index)
{
for (int i = index; i < a.Count; ++i)
a[i] <<= amount;
}
public static Bitable ShiftLeft(Bitable a, int amount, int index = 0)
{
Bitable result = new Bitable(a);
ShiftLeft(ref result, ref amount, ref index);
return result;
}
public static void ShiftRight(ref Bitable a, ref int amount, ref int index)
{
for (int i = index; i < a.Count; ++i)
a[i] >>= amount;
}
public static Bitable ShiftRight(Bitable a, int amount, int index = 0)
{
Bitable result = new Bitable(a);
ShiftRight(ref result, ref amount, ref index);
return result;
}
}
#endregion
IComplementor
- The interface which defines Complementors.
#region IComplementor
public interface IComplementor
{
int Complements { get; }
IManipulator Manipulator { get; }
}
#endregion
#region Complementor
public abstract class Complementor : IComplementor
{
public abstract int Complements { get; }
public abstract IManipulator Manipulator { get; }
}
#endregion
#region TwosComplementor
public class TwosComplimentor : Complementor
{
public static int ComplementsOf = 2;
public override int Complements
{
get { return TwosComplimentor.ComplementsOf; }
}
public override IManipulator Manipulator
{
get { return Manipulator; }
}
}
#endregion
Complementor
- The base class of all Complementors.
Complementors. A complementor is responsible for reading numbers from a
Bitable
in a designed form.
#region Complementor
public abstract class Complementor : IComplementor
{
public abstract int Complements { get; }
public abstract IManipulator Manipulator { get; }
}
#endregion
Number
- A Class which sits on top of Bitable
to provide the
default math system. It is aware of the SystemComplimentor as well as it’s own
Complimentor which is by default the TwosComplimentor
. All Compliments
have a
IManipulator
as an abstract property which should be responsible for all
operations.
It solves the Generic Math problem in a new and hopefully not to puzzling way! (Examples included)
Again a proper implementation would abstract this against the IHardware interface and implement proper carrying support inter alia.
The only operator really tested is "+" and that is on purpose to prevent people from re-manufacturing this code if they don't understand it. If you know what you are doing or wait until I release the rest you will see the other operators can be easily implemented.
#region Number
public class Number : Bitable
{
#region Overrides
public override int GetHashCode()
{
return base.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is Number) return ((Number)obj) == this;
return base.Equals(obj);
}
#endregion
#region Constructors
public Number(Complementor complimentor = null) : base() { Complimentor = complimentor ?? DefaultComplimentor; }
public Number(Number other, Complementor complimentor = null) : base(other) { Complimentor = complimentor ?? DefaultComplimentor; }
public Number(Bitable other, Complementor complimentor = null) : base(other) { Complimentor = complimentor ?? DefaultComplimentor; }
public Number(Bits other, Complementor complimentor = null) : base(other) { Complimentor = complimentor ?? DefaultComplimentor; }
public Number(bool Boolean, Complementor complimentor = null)
: this((byte)(Boolean ? 1 : 0))
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(byte Byte, Endian? endian = null, Complementor complimentor = null)
: base(Byte, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(sbyte SByte, Endian? endian = null, Complementor complimentor = null)
: base(SByte, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Int16 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(UInt16 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Int32 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(UInt32 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Int64 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(UInt64 Int, Endian? endian = null, Complementor complimentor = null)
: base(Int, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Single Single, Endian? endian = null, Complementor complimentor = null)
: base(Single, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Double Double, Endian? endian = null, Complementor complimentor = null)
: base(Double, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
public Number(Decimal Decimal, Endian? endian = null, Complementor complimentor = null)
: base(Decimal, endian)
{
Complimentor = complimentor ?? DefaultComplimentor;
}
#endregion
Number<T>
The generic version of Number
(Included) which solves the
generic math problem's of the future...
public class Number<T> : Number
{
#region Constructors
public Number() : base() { }
public Number(Number other) : base(other) { }
public Number(Bitable other) : base(other) { }
public Number(Bits other) : base(other) { }
public Number(bool Boolean)
: this((byte)(Boolean ? 1 : 0)) { }
public Number(byte Byte, Endian? endian = null)
: base(Byte, endian)
{
}
public Number(sbyte SByte, Endian? endian = null)
: base(SByte, endian)
{
}
public Number(Int16 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(UInt16 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(Int32 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(UInt32 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(Int64 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(UInt64 Int, Endian? endian = null)
: base(Int, endian)
{
}
public Number(Single Single, Endian? endian = null)
: base(Single, endian)
{
}
public Number(Double Double, Endian? endian = null)
: base(Double, endian)
{
}
public Number(Decimal Decimal, Endian? endian = null)
: base(Decimal, endian)
{
}
#endregion
What is the purpose of this code?
Well with it you can now more quickly and efficiently emulate
ANY type of hardware using any other type of hardware given you have the memory
to compensate and the CPU speed required to perform the calculations
efficiently.
These classes coupled with the Mono’s SIMD classes can allow developers previously un-thought of levels of performance and interoperability
as well as new ways of using unmanaged languages within the managed language.
For instance I have the areas regioned off for BitableObject
and BitableStruct
etc.
Those classes would eventually be used for advanced
serialization and deserialization.
For example I will only endeavor into talking about the
BitableStruct
.
Ideally say given known layout information
e.g. { int, bool, short, byte, string(4), byte[1] }
You can create a BitableObject
which has dynamically named
members with the values from the memory parsed in the format given to the
BitableObject
.
With this you could allow for new BitableStructLayout
Attributes based on bits
From the BitableObject
/ BitableStructure
SO with memory [0, 0 ,0, 0, 0, 0 ,0, 1] (In Binary) or (In
Decimal = 1)
You can make each BIT field or something else and you don't
care about the names of the properties so you would access them by var X = {
Bool[0], Byte[0] }
I would eventually like to add other concepts which I might choose to add here if people comment but I don't want to give everything away for free but at the same time I want to help everyone progress and see things in new and interesting ways so I will outline a few things I have included also..
Interesting Points
Nothing Requires or utilizes ANY unsafe code or any Interop put it fully supports it!
Inside you will also find PointerGuard
technology (unfinished but the concept is real) which can protect a pointer from operations which you don't want or exceed a maximum address.
CommonIntermediateLanguage which can be used as in anywhere you need to support inline CIL.
Number<T>
- Not very useful and commented out for now...
This allows you to have crazy serialization and deserialization
potentials without relying on the System for BinaryFormatter
or anything else along with so MUCH MORE!
Much more! (PerpetualEnumerators
(Parallel)... )
#region PerpetuatingEnumerable
public class PerpetuatingEnumerable<T> : IEnumerator<T>, IEnumerable<T>, System.Collections.IEnumerator, System.Collections.IEnumerable
{
#region Nested Types
public class PerpetuatingInstruction : Exception { }
public class BreakInstruction : PerpetuatingInstruction { }
public class ContinueInstruction : PerpetuatingInstruction { }
public delegate void PerpetuatingEvent(PerpetuatingEnumerable<T> sender, T state);
#endregion
public event PerpetuatingEvent Perpetuated, Completed;
IEnumerable<T> enumerable;
IEnumerator<T> enumerator;
internal protected void OnPerpetuated(PerpetuatingEnumerable<T> sender, T item) { sender.Perpetuated -= OnPerpetuated; sender.Perpetual = true; }
internal protected void OnCompleted(PerpetuatingEnumerable<T> sender, T item) { sender.Completed -= OnCompleted; }
public bool Perpetual { get; private set; }
public T Current
{
get
{
if (enumerator == null) enumerator = enumerable.AsParallel().GetEnumerator();
return enumerator.Current;
}
}
public PerpetuatingEnumerable(IEnumerable<T> toLoop)
{
if (toLoop == null) throw new ArgumentNullException();
enumerable = toLoop;
enumerator = enumerable.GetEnumerator();
Perpetuated += OnPerpetuated;
Completed += OnCompleted;
}
public PerpetuatingEnumerable(T item) : this(item.Yield()) { }
public PerpetuatingEnumerable(System.Collections.IEnumerable toLoop) : this((IEnumerable<T>)toLoop) { }
public void Dispose()
{
Completed(this, Current);
enumerator.Dispose();
enumerator = null;
enumerable = null;
}
public int Count { get { unchecked { return (int)enumerable.Count(); } } }
object System.Collections.IEnumerator.Current { get { return enumerator.Current; } }
public bool MoveNext()
{
try
{
if (enumerator.MoveNext())
{
return true;
}
else if (enumerable != null)
{
try { enumerator = enumerable.GetEnumerator(); enumerator.MoveNext(); return true; }
catch (InvalidOperationException) { return Perpetuate(); }
catch (BreakInstruction) { return false; }
catch (ContinueInstruction) { return true; }
catch { throw; }
finally { Perpetuated(this, Current); }
}
return false;
}
catch (BreakInstruction) { return false; }
catch (ContinueInstruction) { return true; }
catch (InvalidOperationException) { return Perpetuate(); }
catch { throw; }
}
public void Reset() { enumerator.Reset(); }
public virtual bool Perpetuate() { return MoveNext(); }
public IEnumerator<T> GetEnumerator() { return this; }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return (System.Collections.IEnumerator)GetEnumerator(); }
}
#endregion
Until Next Time! Play with these code samples: (Ran from a MTA Thread)
#region Sandbox
enum StateMachineState : byte
{
None = 0,
Start = 1,
AfterStart = 2,
BeforeEnd = 4,
End = 8,
Invalid = 255
}
private delegate int IntSqaureInvoker(int a, int b);
private delegate long LongSqaureInvoker(long a, long b);
private delegate TReturn MyPrototype<TReturn, TParameter0, TParameter1>(TParameter0 p0, TParameter0 p1);
public static void SandBox()
{
string ILSquare = @"
ldarg.0 //Loads the argument at index 0 onto the evaluation stack.
conv.i8 //Converts the value on top of the evaluation stack to int64.
dup//Copies the current topmost value on the evaluation stack, and then pushes the copy onto the evaluation stack.
mul//Multiplies two values and pushes the result on the evaluation stack.
ret//Returns from the current method, pushing a return value (if present) from the callee's evaluation stack onto the caller's evaluation stack.
";
MyPrototype<int, int, int> prototype = new MyPrototype<int, int, int>((a, b) => 0);
MyPrototype<int, int, int> compiledIl = (MyPrototype<int, int, int>)Media.Common.Bits.CommonIntermediaLanguage.CreateMethod(ILSquare, "Square", prototype);
Console.WriteLine(compiledIl(2, 2));
LongSqaureInvoker compiledIl2 = (LongSqaureInvoker)Media.Common.Bits.CommonIntermediaLanguage.CreateMethod(ILSquare, "Square", typeof(long), new Type[] { typeof(long), typeof(long) }, typeof(LongSqaureInvoker));
Console.WriteLine(compiledIl2(4, 2));
Media.Common.Bits.Transistor t = new Common.Bits.Transistor()
{
Value = true
};
Console.WriteLine(t.Value);
t.Value = false;
Console.WriteLine(t.Value);
t.Value = true;
Console.WriteLine(t.Value);
Media.Common.Bits.Bits bits = new Media.Common.Bits.Bits(136);
Console.WriteLine(string.Join(",", (bits as IEnumerable<bool>).ToArray()));
Console.WriteLine(string.Join(",", (Media.Common.Bits.BitsExtensions.GetBits(bits, 0, 4))));
Console.WriteLine(string.Join(",", (Media.Common.Bits.BitsExtensions.GetBits(bits, 4, 4))));
Media.Common.Bits.Bitable bitss = 136;
Console.WriteLine(string.Join(",", (Media.Common.Bits.BitsExtensions.GetBits(bitss))));
Media.Common.Bits.Bits two = 1 + 1;
System.Console.WriteLine(two == 1 + 1);
Media.Common.Bits.Bitable four = 2 + 2;
System.Console.WriteLine(four == 2 + 2);
Media.Common.Bits.Bitable overflow = (long)2 + int.MaxValue;
System.Console.WriteLine(overflow == (long)int.MaxValue + 2);
Media.Common.Bits.Number testNumber = 2;
int result = testNumber + 2;
System.Console.WriteLine(testNumber == 4);
System.Console.WriteLine(result == 4);
System.Console.WriteLine(testNumber + 4);
testNumber += 4;
System.Console.WriteLine(testNumber);
List<decimal> xs = new List<decimal>()
{
0.09m,
0.1m,
0.2m,
0.3m,
0.4m,
0.5m,
};
List<Media.Common.Bits.Number> doubles = new List<Common.Bits.Number>();
double val = 0.1;
xs.ForEach(d => doubles.Add(new Media.Common.Bits.Number((Media.Common.Bits.Number)d + (Media.Common.Bits.Number)val)));
Media.Common.ArraySegmentList<int> asl = new Media.Common.ArraySegmentList<int>(10);
for (int x = 0; x < 105; ++x)
{
asl.Add(x);
}
foreach (ArraySegment<int> segment in asl.Segments)
{
Console.WriteLine(string.Join("-", segment.Array));
}
System.IO.MemoryStream test = new System.IO.MemoryStream();
test.WriteByte(0);
test.WriteByte(1);
test.WriteByte(2);
test.WriteByte(3);
test.WriteByte(4);
test.WriteByte(5);
test.WriteByte(6);
test.WriteByte(7);
test.Position = 0;
Media.Common.EnumerableByteStream ebs = new Common.EnumerableByteStream(test);
foreach (byte b in ebs.Take(4)) Console.WriteLine(b);
ebs[8] = 8;
Console.WriteLine(ebs[7] == 7);
Console.WriteLine(ebs[8] == 8);
Console.WriteLine(ebs.IndexOf(7) + " " + (ebs[ebs.IndexOf(7)] == 7));
ebs.Insert(6, 7);
Console.WriteLine(ebs.IndexOf(7) + " " + (ebs[ebs.IndexOf(7)] == 6));
ebs.Insert(7, 7);
Console.WriteLine(ebs[ebs.IndexOf(7)]);
byte[] data = new byte[] { 0, 1, 2, 3 };
using (Media.Common.Iterator<byte> it = new Media.Common.Iterator<byte>(data))
{
using (IEnumerator<byte> enumerator = it)
{
while (enumerator.MoveNext())
{
Console.WriteLine(enumerator.Current);
it.SetCurrent(7);
Console.WriteLine(it.Current);
Console.WriteLine(enumerator.Current);
}
it.SetCurrent(7);
it.Reset();
foreach (byte B in it) Console.WriteLine(B);
}
}
foreach (byte B in data) Console.WriteLine(B);
Media.Common.EnumerableByteStream ebsx = new Common.EnumerableByteStream(test, 0, 6);
foreach (byte b in ebsx)
{
Console.WriteLine(b);
}
var validStates = ((IEnumerable<StateMachineState>)Enum.GetValues(typeof(StateMachineState))).Where(s => s != StateMachineState.Invalid);
var currentState = StateMachineState.Start;
var perpetual = new Media.Common.PerpetuatingEnumerable<StateMachineState>(currentState);
System.Threading.Tasks.Task simpleTask = new System.Threading.Tasks.Task(() => perpetual.Any(run => !validStates.Contains(run)));
simpleTask.Start();
int i = 0;
perpetual.Perpetuated += (p, s) =>
{
if (s == StateMachineState.Invalid) throw new Media.Common.PerpetuatingEnumerable<StateMachineState>.BreakInstruction();
Console.Write("----------------------------" + ++i + "----------------------------");
};
while (!simpleTask.IsCompleted)
{
Console.WriteLine("Looping" + currentState);
currentState++;
}
Console.WriteLine("Not Looping" + currentState);
}
#endregion
I personally would have also have done more work on the Manipulator
and IManipulaor.
They need better definition and should follow an IHardware
interface to allow this.
The same has been done with the Complementor for obvious reasons (or not so)
GPU
should added via the same abstraction and should be able support other things besides GPU's
also...
I would also personally like to write a Real Time Kernel in C# but the uses would be very limited at this point as the hardware to run .Net in a native state are not commonly available.
Until that time I will be working on Managed Media Aggregation as well as other cool ideas like Net 7 CSharp or D#
Let me know if you liked this article or found any of the concepts provided useful or interesting!
v//
Livin in a lonely world, caught the midnight train going anywhere... Only thing is it was a runaway train... and it ain't ever goin back...
мала ка на хари, Trahentes ex exsilium
√