// buffertest.cc
//
//      Mike O'Donnell
//
//	Simple test case for the bounded buffer problem.
//
//	Two writer threads and two reader threads compete for a single
//      bounded buffer. The size of the buffer is set by input to
//      nachos. Try this example both with and without randomizing
//      option -rs. The results may surprise you at first. Make sure
//      you understand why the threads interleave the way that they
//      do. Draw conclusions about the fairness or unfairness of the
//      simple implementation of bounded buffers using semaphores.
//

#include "system.h"
#include "synch.h"

//----------------------------------------------------------------------
// WriterThreadAlph
//----------------------------------------------------------------------

void
WriterThreadAlph(int testBufferInt) {
    BoundedBuffer *testBuffer = (BoundedBuffer *)testBufferInt;

    printf("--- a -\n");
    testBuffer->Write('a');
    printf("--- b -\n");
    testBuffer->Write('b');
    printf("--- c -\n");
    testBuffer->Write('c');
    printf("--- d -\n");
    testBuffer->Write('d');
    printf("--- e -\n");
    testBuffer->Write('e');
    printf("--- f -\n");
    testBuffer->Write('f');
    printf("--- g -\n");
    testBuffer->Write('g');
    printf("--- h -\n");
    testBuffer->Write('h');
    printf("--- i -\n");
    testBuffer->Write('i');
    printf("--- j -\n");
    testBuffer->Write('j');
}

//----------------------------------------------------------------------
// WriterThreadNum
//----------------------------------------------------------------------

void
WriterThreadNum(int testBufferInt) {
    BoundedBuffer *testBuffer = (BoundedBuffer *)testBufferInt;

    printf("--- - 0\n");
    testBuffer->Write('0');
    printf("--- - 1\n");
    testBuffer->Write('1');
    printf("--- - 2\n");
    testBuffer->Write('2');
    printf("--- - 3\n");
    testBuffer->Write('3');
    printf("--- - 4\n");
    testBuffer->Write('4');
    printf("--- - 5\n");
    testBuffer->Write('5');
    printf("--- - 6\n");
    testBuffer->Write('6');
    printf("--- - 7\n");
    testBuffer->Write('7');
    printf("--- - 8\n");
    testBuffer->Write('8');
    printf("--- - 9\n");
    testBuffer->Write('9');
}


//----------------------------------------------------------------------
// ReaderThreadL
//----------------------------------------------------------------------

void
ReaderThreadL(int testBufferInt) {
    BoundedBuffer *testBuffer = (BoundedBuffer *)testBufferInt;

    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
    printf("%c -\n", testBuffer->Read());
}

//----------------------------------------------------------------------
// ReaderThreadR
//----------------------------------------------------------------------

void
ReaderThreadR(int testBufferInt) {
    BoundedBuffer *testBuffer = (BoundedBuffer *)testBufferInt;

    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
    printf("- %c\n", testBuffer->Read());
}

//----------------------------------------------------------------------
// BufferTest
//----------------------------------------------------------------------

void
BufferTest()
{
    int bufferSize;

    printf("TESTING BOUNDED BUFFERS\n\n");

    printf("Buffer size: ");
    scanf("%i", &bufferSize);
    BoundedBuffer *testBuffer = new BoundedBuffer("testBuffer", bufferSize);

    DEBUG('t', "Entering Buffer Test\n");

    Thread *t1 = new Thread("alphabetic writer thread");
    Thread *t2 = new Thread("numeric writer thread");
    Thread *t3 = new Thread("left reader thread");
    Thread *t4 = new Thread("right reader thread");

    t1->Fork(WriterThreadAlph, (int)testBuffer);
    t2->Fork(WriterThreadNum, (int)testBuffer);
    t3->Fork(ReaderThreadL, (int)testBuffer);
    t4->Fork(ReaderThreadR, (int)testBuffer);
}
