migration C#, Java, C++ (day 4)

logo

Today we translate some basics of threading and locking. For the ones, who follow the C# hardcore posts, I will cover the C# side in more detail on Tuesday.
Further down I also cover operator overloading today.

Some background info:
Deadlocks
WaitOne

There are no direct equivalents in C++ for the C# lock keyword, the Monitor class and Semaphores unless you are using the .Net Framework on the C++ side. This is clearly not what you want to do. The speed advantage of C++ would end in smoke.
Mutexes do exist for both C# and C++. You have to get used to using Mutexes in C++. They are hardly used in C#, but found often in C++.
The C++ mutex is not the same as the C# Mutex. This is as confusing as using a C# List and think it would be similar to a C++ list.
The C++ mutex is (depite its name) much closer to the C# Monitor class. It definitely is not as public as the C# Mutex, which is known to each process across the entire computer system.

Java looks quite retarded today. We already know that Java does not support pointers. Today it becomes even worse. There is no C# type mutex and no operator overloading.

Lock, Monitor, Semaphore

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

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

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); 
   }
} //

// Limits the number of threads that can access a resource or pool of resources concurrently. 
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(); 
   }
} //
public final void DoSomething() {
  System.out.println("Good night my dear thread " + Thread.currentThread().getId());
  try {
    Thread.sleep(2000);
  }
  catch (InterruptedException e) {
    e.printStackTrace();
  }
}

private Object lAnyObject2 = new Object();

public final void LockUsage() {
  synchronized (lAnyObject2) {
    DoSomething();
  }
}

// Limits the number of threads that can access a resource or pool of resources concurrently.
private static java.util.concurrent.Semaphore _Semaphore = new java.util.concurrent.Semaphore(3); // three objects allowed to access concurrently                                                                                                    

public final void SemaphoreUsage() {
  try {
    _Semaphore.acquire();
    DoSomething();
  }
  catch (InterruptedException e) { e.printStackTrace(); }
  finally { _Semaphore.release(); }
}

Mutex

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

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(); 
   }
} //
// no mutexes available
// use the synchronized block
void DoSomething() {
    cout << "Good night my dear thread " << this_thread::get_id() << endl; 
    this_thread::sleep_for(chrono::milliseconds(2000));
}

mutex _Mutex;
void MutexUsage(){
	_Mutex.lock();
	try {
		DoSomething();
	}
	catch (string e){
		_Mutex.unlock();
		throw e;
	}
	_Mutex.unlock();
}

mutex _Mutex2;
void MultipleMutexUsage(){
	int x = try_lock(_Mutex, _Mutex2);
	if (x == -1) {
		DoSomething();
		_Mutex.unlock();
		_Mutex2.unlock();
	}
	else cout << "failed to obtain lock for " << (x ? "_Mutex" : "_Mutex2") << endl;
}

void MutexUsage_For_Forgetful_People(){
	lock_guard<mutex> guard(mutex);
	DoSomething();
} // auto unlocks here

operator overloading

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();
} //
// there is no operator overloading available in Java
#include <string>
#include <iostream>
#include <memory>

using namespace std;

namespace OperatorOverloading {

	class myClass {

	private:
		int *Values = new int[] { 1, 2, 3 };

	public:
		myClass &operator + (const myClass &b);
		//const string operator + (const myClass &b); // not possible to distinguish by return type only
		const string myClass::operator + (int &i);
		myClass &operator + (const int &i); // this is possible 🙂
		double operator *(const myClass &b);
		const string ToString();

	}; // class

	myClass &myClass::operator + (const myClass &b) {
		myClass *lNewClass = new myClass();
		for (int i = 0; i < 3; i++) lNewClass->Values[i] = Values[i] + b.Values[i];
		return *lNewClass;
	}

	myClass &myClass::operator + (const int &i) {
		myClass *lNewClass = new myClass();
		for (int i = 0; i < 3; i++) lNewClass->Values[i] = 3 + Values[i];
		return *lNewClass;
	}

	const string myClass::operator + (int &i) {
		return ">> " + ToString() + " -- " + to_string(i) + "<<";
	}

	// const string myClass::operator + (const myClass &b) {} not possible

	double myClass::operator *(const myClass &b) {
		int lSum = 0;
		for (int i = 0; i < 3; i++) lSum += (this->Values[i]) * (b.Values[i]);
		return lSum;
	}

	const string myClass::ToString() {
		string s1 = to_string(Values[0]);
		string s2 = to_string(Values[1]);
		string s3 = to_string(Values[2]);
		return "Values: " + s1 + " " + s2 + " " + s3;
	}

} // namespace

int main() {	
	using namespace OperatorOverloading;
	myClass a, b;	

	myClass c = a + b;	
	cout << c.ToString() << endl; // Values: 2 4 6
	
	double d = a * b;
	cout << d << endl; // 14
	
	myClass e = a + 3;
	cout << c.ToString() << endl; // Values: 5 7 9
	
	cin.get();
	return 0;
}
Advertisements

About Bastian M.K. Ohta

Happiness only real when shared.

Posted on February 28, 2014, in C#, C++, Java and tagged , , , , , , , . Bookmark the permalink. 1 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 )

Google+ photo

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

Twitter picture

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

Facebook photo

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

Connecting to %s

%d bloggers like this: