C# to C++ (advanced), review of day 4, locks and operators

As promised I am going to explain the C# side of post C# to C++ (day 4) today.
Let’s start with a dummy method. We will need it in the examples to fill in arbitrary code at the right places.

public void DoSomething() {
   Console.WriteLine("Good night my dear thread " + Thread.CurrentThread.ManagedThreadId);
   Thread.Sleep(2000);
} //

Lock

This is the standard. The Lock keyword is used frequently. The syntax is simple and locks are easy to deal with. My speed tests also tell that the speed impact of locks is negligible. Thus you can use locks without hesitation when needed.

object lAnyObject2 = new object();
public void LockUsage() {
   lock (lAnyObject2) {
      DoSomething();
   }
} //

Monitor

Locks are like macros that use the more complex Monitor class, which has more specific methods. If you don’t use the complexity of the Monitor class, then you are better of by simply using locks, which provide much better code legibility. Microsoft describes it like this:
“The functionality provided by the Enter and Exit methods is identical to that provided by the C# lock statement, except that lock wraps the Enter(Object, Boolean) method overload and the Exit method in a try…finally block to ensure that the monitor is released.”

object lAnyObject1 = new object();
public void MonitorUsage() {
   bool lLocked = false;
   try {
      Monitor.Enter(lAnyObject1, ref lLocked);  // using System.Threading;
      DoSomething();
   }
   finally {
      if (lLocked) Monitor.Exit(lAnyObject1);
   }
} //

Semaphore

Semaphores are used to limit the number of threads that can access resources. Let’s say you want to limit the output of a loudspeaker, because you cannot listen to five different sounds simultaneously. Nevertheless you want to hear urgent incoming chat message sounds from your friends while listening to nice background sounds of a game. In that case you could limit the number of threads using a resource to two. Or you are writing to a hard disk, which can deal with some simultaneous write operations. Still you want to limit the number of threads writing at the same time.
There is a slim class of Semaphores as well. SemaphoreSlim provides a lightweight semaphore class that doesn’t use Windows kernel semaphores.

private static Semaphore _Semaphore = new Semaphore(3, 3); // three objects allowed to access concurrently
public void SemaphoreUsage() {
   bool lLocked = false;
   try {
      lLocked = _Semaphore.WaitOne();
      DoSomething();
   }
   finally {
      if (lLocked) _Semaphore.Release();
   }
} //

Mutex

Mutexes are used across the system. They are identified by strings. Make sure you use unique strings to avoid conflicts. Let’s say you are running an application, which sets a Mutex. By mistake the user tries to start the same application again. But you can check the Mutex now and close/not start the second application.

private const string cMutexName = "MyMutex"
private static Mutex _Mutex = new Mutex(false, cMutexName);  // known by every process
public void MutexUsage() {
   bool lLocked = false;

   try {
      // optional complexity: access rights
      //bool lNewCreation;
      //MutexSecurity lSecurity = new MutexSecurity();
      //SecurityIdentifier lId = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
      //MutexRights lRights = MutexRights.Synchronize | MutexRights.Modify;
      //lSecurity.AddAccessRule(new MutexAccessRule(lId, lRights, AccessControlType.Allow));
      //_Mutex = new Mutex(false, cMutexName, out lNewCreation, lSecurity);
      //MutexSecurity lReverse = _Mutex.GetAccessControl();

      lLocked = _Mutex.WaitOne(2000); // You can the option to set a time limit. Here 2000 milliseconds.
      if (!lLocked) {
         Console.WriteLine("Try again later. Mutex is used by another process or thread.");
      }

      DoSomething();
   }
   finally {
      if (lLocked == true) _Mutex.ReleaseMutex();
   }
} //

Operator overloading

It does look easy, but can cause complex situations. All you have to do is to declare a method as static and replace the method name by the word operator followed by the operator itself. The return value can be of any type. The parameters should have at least one type that equals the class type. The order of the parameters is important.

Let’s have a look at the example source code of post C# to C++ (day 4) again:

public class myClass {
   // this class is not thread safe
 
   int[] Values = { 1, 2, 3 };
 
   public static myClass operator +(myClass a, myClass b) {
      int n = a.Values.Length;
      myClass lNewClass = new myClass();
      for (int i = 0; i < n; i++) lNewClass.Values[i] = a.Values[i] + b.Values[i];
      return lNewClass;
   } //      
 
   public static double operator *(myClass a, myClass b) {
      int n = a.Values.Length;
      int lSum = 0;
      for (int i = 0; i < n; i++) lSum += a.Values[i] * b.Values[i];
      return lSum;
   } //
 
   public static string operator +(string a, myClass b) {
      //return ">> " + a + b + "<<";  // WRONG! causes recursion
      return ">> " + a + b.ToString() + "<<";
   } //
 
   // I will explanation this in my post on Tuesday 4 February 2014
   // uncomment this and play with it (=>hardcore C#)
   //public static string operator +(myClass a, string b) {
   //   //return ">> " + a + b + "<<";  // WRONG! causes recursion
   //   return ">> " + a + b.ToString() + "<<";
   //} //
   // becomes even more hardcore when you have two conflicting overloads
 
   public override string ToString() {
      return "Values: " + Values[0] + " " + Values[1] + " " + Values[2] + " ";
   } //
 
} // class
 
public static void test() {
   myClass a = new myClass();
   myClass b = new myClass();
   myClass c = a + b;
   double d = a * b;
   Console.WriteLine("(Sum) " + c);  // ">> (Sum) Values: 2 4 6 <<"
   Console.WriteLine("(Sum) " + c.ToString());  // "(Sum) Values: 2 4 6"
   Console.WriteLine(c + " (Sum)");  // "Values: 2 4 6  (Sum)"
   Console.WriteLine(d);  // 14
   Console.ReadLine();
} //
source code line operator called output
myClass c = a + b; public static myClass operator +(myClass a, myClass b) {…}
double d = a * b; public static double operator *(myClass a, myClass b) {…}
Console.WriteLine(“(Sum) ” + c); public static string operator +(string a, myClass b) {…} >> (Sum) Values: 2 4 6 <<
Console.WriteLine(“(Sum) ” + c.ToString()); [not part of myClass]
operator overload “+” of the string class
(Sum) Values: 2 4 6
Console.WriteLine(c + ” (Sum)”); c.ToString() is called by the string class operator overload “+” for objects Values: 2 4 6  (Sum)

You are using operator overloading quite often without noticing it. A quick example is:

DateTime x = DateTime.Now;
DateTime y = x.AddMinutes(5);
TimeSpan t = y - x;  // operator "-" is overloaded and returns a TimeSpan.

Let’s make it more difficult now.
Uncomment public static string operator +(myClass a, string b) {…}. The statement Console.WriteLine(c + ” (Sum)”) now prints “>> >> Values: 2 4 6 << (Sum)<<“.
First the operator public static string operator +(myClass a, string b) {…} is called. This operator indirectly calls another operator public static string operator +(string a, myClass b) {…}, because the code return “>> ” + a + b.ToString() + “<<"; was called, which started with a string “>> ” + a class.

Implicit

This is used to avoid explicit cast operations and convert implicitly. But more precisely we talk about User-defined conversions.

public class ClassX {
   private readonly double _Value;
   public ClassX(double xInitValue) { _Value = xInitValue; } // constructor
   public override string ToString() { return "CLASS"; }

   // cast operation: (double)ClassX;
   public static implicit operator double(ClassX xClassX) { return xClassX._Value; }
   // cast operation: (ClassX)double;
   public static implicit operator ClassX(double xDouble) { return new ClassX(xDouble); }
}

public static void test() {
   int i = 10;
   double d1 = i;          // implicit cast operation
   double d2 = (double)i;  // explicit cast operation

   ClassX c = new ClassX(99.0);
   double d3 = c;          // implicit cast operation
   double d4 = (double)c;  // explicit cast operation
   c = 1.2;

   Console.WriteLine("class or double? " + c);  // "CLASS"
   Console.ReadLine();
}

Conflicts

So what happens when you have two classes with opposing declarations? Luckily the compiler is smart enough to detect these issues. The below source code does not compile at all. The statement Console.WriteLine(a + b) causes an error message like: “The call is ambiguous between the following methods or properties: ‘…A.operator +(…A, …B)’ and ‘B.operator +(…A, …B)'”.
The next statement Console.WriteLine(b + a) is not even a real problem. We did not define any operator overloading. Thus the compiler complains “Operator ‘+’ cannot be applied to operands of type ‘…B’ and ‘…A'”

public class A {
   public static string operator +(A a, B b) { return "class A"; }
} // class
public class B {
   public static string operator +(A a, B b) { return "class B"; }
} // class

public static void test() {
	A a = new A();
	B b = new B();
	Console.WriteLine(a + b);
	Console.WriteLine(b + a);
} //

About Bastian M.K. Ohta

Happiness only real when shared.

Posted on March 4, 2014, in Advanced, C#, Threading and tagged , , , , , , , , , , , , , . Bookmark the permalink. Leave a comment.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: