关于在C#中多线程处理仿真器的建议。模式/概念

时间:2017-01-25 21:42:28

标签: c# multithreading emulation

我正在使用MIPS模拟器作为学习项目。为了获得所需的性能,我希望每个处理器始终在自己的线程中休眠,并且当DMA传输发生时,它们开始处理。

之前我使用过BackgroundWorker,刚刚开始使用async / away指令,我读过有关线程池的内容。 "记忆空间"将被共享,因此DMA状态位是"自然"锁定机制。这些线程技术似乎没有做我想做的事情。我错过了什么?

也许这个代码示例(编译,不起作用)将解释我的想法。

public class ThreadingEmulatorCode
{
    static Memory memory = new Memory();

    public ThreadingEmulatorCode()
    {
        CPU cpu = new CPU();
        memory.OnDMAZero += cpu.zero.Execute(new DMAEventArgs());
        memory.OnDMAOne += cpu.one.Execute(new DMAEventArgs());
        cpu.Run(ref memory);
    }
}

public delegate void dmazero(DMAEventArgs args);
public delegate void dmaone(DMAEventArgs args);

public class DMAEventArgs : EventArgs
{
    public byte[] Data { get; set; }
    public uint Address { get; set; }
}

public class Memory
{
    public event dmazero OnDMAZero;
    public event dmaone OnDMAOne;

    private const uint CoprocZeroDMA = 0x1FC00000;
    private const uint CoprocOneDMA = 0xBFC00000;
    private byte[] memory;

    public Memory()
    {
        this.memory = new byte[(8 * 1024 * 1024)];
    }

    public byte this[uint address]
    {
        get
        {
            return memory[address];
        }
        set
        {
            memory[address] = value;
            if (address == CoprocZeroDMA && OnDMAZero != null)
                OnDMAZero(new DMAEventArgs());
            if (address == CoprocOneDMA && OnDMAOne != null)
                OnDMAOne(new DMAEventArgs());
        }
    }
}

public class CPU
{
    public CoprocZero zero;
    public CoprocOne one;

    public void Run(ref Memory memory)
    {
         /* Start Executing Instructions */
    }

    public CPU()
    {
        zero = new CoprocZero();
        one = new CoprocOne();
    }
}

public class CoprocZero
{
    public CoprocZero(/* Start Listening Thread */) { }

    public dmazero Execute(DMAEventArgs dmaEvent)
    {
        /* Process DMA'd Data */
        throw new NotImplementedException();
    }
}

public class CoprocOne
{
    public CoprocOne(/* Start Listening Thread */) { }

    public dmaone Execute(DMAEventArgs dmaEvent)
    {
        /* Process DMA'd Data */
        throw new NotImplementedException();
    }
}

想法或建议?感谢。

1 个答案:

答案 0 :(得分:0)

看起来我只需要花更多时间在代码上。抱歉。我最初期望在TryPeek上的紧张时间最大CPU,但它在进程列表中位于零CPU。我还没有验证总体性能,但我认为这样可行。

// Code to Test
// ThreadingExampleCode stackOverflow = new ThreadingExampleCode();
// Thread.Sleep(new TimeSpan(1, 0, 0));
public class ThreadingExampleCode
{
    public static Memory memory;
    private CoprocZero zero;
    private CoprocOne one;
    private CPU cpu;
    private Thread coprocZero;
    private Thread coprocOne;
    ConcurrentQueue<uint> coprocZeroQueue = new ConcurrentQueue<uint>();
    ConcurrentQueue<uint> coprocOneQueue = new ConcurrentQueue<uint>();

    public ThreadingExampleCode()
    {
        memory = new Memory();
        memory.OnDMAZero += MemoryOnOnDmaZero;
        memory.OnDMAOne += MemoryOnOnDmaOne;

        cpu = new CPU(memory);
        zero = new CoprocZero(memory, coprocZeroQueue);
        one = new CoprocOne(memory, coprocOneQueue);
        coprocZero = new Thread(zero.RunParm);
        coprocZero.Start();

        coprocOne = new Thread(one.RunParm);
        coprocOne.Start();

        cpu.Run();
    }

    private void MemoryOnOnDmaOne(DMAEventArgs args)
    {
        coprocOneQueue.Enqueue(args.Address);
    }

    private void MemoryOnOnDmaZero(DMAEventArgs args)
    {
        coprocZeroQueue.Enqueue(args.Address);
    }
}

public delegate void dmazero(DMAEventArgs args);

public delegate void dmaone(DMAEventArgs args);

public class DMAEventArgs : EventArgs
{
    public uint Address { get; set; }
}

public class Memory
{
    public event dmazero OnDMAZero;
    public event dmaone OnDMAOne;

    public const uint CoprocZeroDMA = 1 * 1024 * 1024;
    public const uint CoprocOneDMA = 2 * 1024 * 1024;
    private byte[] memory;

    public Memory()
    {
        this.memory = new byte[(8 * 1024 * 1024)];
    }

    public byte this[uint address]
    {
        get { return memory[address]; }
        set
        {
            memory[address] = value;
            if (address == CoprocZeroDMA && OnDMAZero != null)
                OnDMAZero(new DMAEventArgs());
            if (address == CoprocOneDMA && OnDMAOne != null)
                OnDMAOne(new DMAEventArgs());
        }
    }
}

public class CPU
{
    private Memory memory;
    public CPU(Memory inMemory)
    {
        memory = inMemory;
    }

    public void Run()
    {
        /* Start Executing Instructions */
        memory[Memory.CoprocZeroDMA] = 0x01;
        memory[Memory.CoprocOneDMA] = 0x01;
    }
}

public class CoprocZero
{
    private ConcurrentQueue<uint> queueToMonitor;
    private Memory memory;
    public CoprocZero(Memory inMemory, ConcurrentQueue<uint> queue)
    {
        memory = inMemory;
        queueToMonitor = queue;
    }

    public void RunParm()
    {
        uint memoryAddress;
        while (!queueToMonitor.TryPeek(out memoryAddress)) { };

        if (queueToMonitor.TryDequeue(out memoryAddress))
        {
            Debugger.Break();
        }
    }
}

public class CoprocOne
{
    private Memory memory;
    private ConcurrentQueue<uint> queueToMonitor;
    public CoprocOne(Memory inMemory, ConcurrentQueue<uint> queue)
    {
        memory = inMemory;
        queueToMonitor = queue;
    }

    public void RunParm()
    {
        uint memoryAddress;
        while (!queueToMonitor.TryPeek(out memoryAddress)) { };

        if (queueToMonitor.TryDequeue(out memoryAddress))
        {
            Debugger.Break();
        }
    }
}