Listing 1

using namespace System;
using namespace System::Threading;

int main()
{
/*1*/   MessageBuffer^ m = gcnew MessageBuffer;

/*2a*/  ProcessMessages^ pm = gcnew ProcessMessages(m);
/*2b*/  Thread^ pmt = gcnew Thread(gcnew ThreadStart(pm,
            &ProcessMessages::ProcessMessagesEntryPoint));
/*2c*/  pmt->Start();

/*3a*/  CreateMessages^ cm = gcnew CreateMessages(m);
/*3b*/  Thread^ cmt = gcnew Thread(gcnew ThreadStart(cm, 
            &CreateMessages::CreateMessagesEntryPoint));
/*3c*/  cmt->Start();

/*4*/   cmt->Join();
/*5*/   pmt->Interrupt();
/*6*/   pmt->Join();

    Console::WriteLine("Primary thread terminating");
}

public ref class MessageBuffer 
{
    String^ messageText;
public:
    void SetMessage(String^ s)
    {
/*7*/       Monitor::Enter(this);
            messageText = s;
/*8*/       Monitor::Pulse(this);
            Console::WriteLine("Set new message {0}", messageText);
            Monitor::Exit(this);
    }

    void ProcessMessages()
    {
/*9*/       Monitor::Enter(this);
            while (true)
            {
                try
                {
/*10*/              Monitor::Wait(this);
                }
            catch (ThreadInterruptedException^ e)
                {
            Console::WriteLine("ProcessMessage interrupted");
                return;
            }

            Console::WriteLine("Processed new message {0}", messageText);
        }
        Monitor::Exit(this);
    }
};

public ref class CreateMessages
{
    MessageBuffer^ msg;
public:
    CreateMessages(MessageBuffer^ m)
    {
        msg = m;
    }

    void CreateMessagesEntryPoint()
    {
        for (int i = 1; i <= 5; ++i)
        {
            msg->SetMessage(String::Concat("M-", i.ToString()));
            Thread::Sleep(2000);
        }
        Console::WriteLine("CreateMessages thread terminating");
    }
};

public ref class ProcessMessages
{
    MessageBuffer^ msg;
public:
    ProcessMessages(MessageBuffer^ m)
    {
        msg = m;
    }

    void ProcessMessagesEntryPoint()
    {
        msg->ProcessMessages();
        Console::WriteLine("ProcessMessages thread terminating");
    }
};