Listing 2
using namespace System;
using namespace System::Threading;
public ref class Point
{
int x;
int y;
public:
// define read-write instance properties X and Y
property int X
{
int get() { return x; }
void set(int val) { x = val; }
}
property int Y
{
int get() { return y; }
void set(int val) { y = val; }
}
// ...
void Move(int xor, int yor)
{
/*1a*/ Monitor::Enter(this);
X = xor;
Y = yor;
/*1b*/ Monitor::Exit(this);
}
virtual bool Equals(Object^ obj) override
{
// ...
if (GetType() == obj->GetType())
{
int xCopy1, xCopy2, yCopy1, yCopy2;
Point^ p = static_cast<Point^>(obj);
/*2a*/ Monitor::Enter(this);
xCopy1 = X;
xCopy2 = p->X;
yCopy1 = Y;
yCopy2 = p->Y;
/*2b*/ Monitor::Exit(this);
return (xCopy1 == xCopy2) && (yCopy1 == yCopy2);
}
return false;
}
virtual int GetHashCode() override
{
int xCopy;
int yCopy;
/*3a*/ Monitor::Enter(this);
xCopy = X;
yCopy = Y;
/*3b*/ Monitor::Exit(this);
return xCopy ^ (yCopy << 1);
}
virtual String^ ToString() override
{
int xCopy;
int yCopy;
/*4a*/ Monitor::Enter(this);
xCopy = X;
yCopy = Y;
/*4b*/ Monitor::Exit(this);
return String::Concat("(", xCopy, ",", yCopy, ")");
}
};
public ref class ThreadY
{
Point^ pnt;
bool mover;
public:
ThreadY(bool isMover, Point^ p)
{
mover = isMover;
pnt = p;
}
void StartUp()
{
if (mover)
{
for (int i = 1; i <= 10000000; ++i)
{
/*1*/ pnt->Move(i, i);
}
}
else
{
for (int i = 1; i <= 10; ++i)
{
/*2*/ Console::WriteLine(pnt); // calls ToString
Thread::Sleep(10);
}
}
}
};
int main()
{
Point^ p = gcnew Point;
/*1*/ ThreadY^ o1 = gcnew ThreadY(true, p);
/*2*/ Thread^ t1 = gcnew Thread(gcnew ThreadStart(o1, &ThreadY::StartUp));
/*3*/ ThreadY^ o2 = gcnew ThreadY(false, p);
/*4*/ Thread^ t2 = gcnew Thread(gcnew ThreadStart(o2, &ThreadY::StartUp));
t1->Start();
t2->Start();
Thread::Sleep(100);
/*5*/ Console::WriteLine("x: {0}", p->X);
/*6*/ Console::WriteLine("y: {0}", p->Y);
/*7*/ t1->Join();
t2->Join();
}