Blog Archives

migration C#, Java, C++ (day 6), MySQL

logo
It is nearly midnight now. 7 minutes are left. Phew, I made it. Good night.
Discipline or stupidity? I guess both 😉
Was fun though. I am achieving my targets.
But now I need something soft, no more hardcore today. Maybe a cushion … Zzzzzzz

MySQL

private void ExecuteNonQuery(MySqlConnection xConnection, string xCommand) {
   MySqlCommand lCommand = xConnection.CreateCommand();
   lCommand.CommandText = xCommand;
   lCommand.ExecuteNonQuery();
} //

private void ExecuteNonQueryAddRow(MySqlConnection xConnection, string xName, DateTime xBirthday) {
   MySqlCommand lCommand = xConnection.CreateCommand();
   lCommand.CommandText = "INSERT INTO test (name, birthdate) values (@name, @birthdate)";
   MySqlParameterCollection lParams = lCommand.Parameters;        
   lParams.AddWithValue("@name", xName);
   lParams.AddWithValue("@birthdate", xBirthday);
   lCommand.ExecuteNonQuery();
} //

private DataTable ExecuteQuery(MySqlConnection xConnection, string xCommand) {
   MySqlCommand lCommand = xConnection.CreateCommand();
   lCommand.CommandText = xCommand;
   MySqlDataAdapter lAdapter = new MySqlDataAdapter(lCommand);
   DataSet lDataSet = new DataSet();
   lAdapter.Fill(lDataSet);
   return lDataSet.Tables[0];
} //

public void MySqlConnectionTest() {
   string lConnectionString = "Server=127.0.0.1;Database=ohta;Uid=root;Pwd=root;";

   try {
      using (MySqlConnection lConnection = new MySqlConnection(lConnectionString)) {
         lConnection.Open();

         //DataTable lSchema = lConnection.GetSchema(); // not required to get or set anything, see lConnectionString             

         // create a new table
         string lField1 = "id INT  NOT NULL AUTO_INCREMENT,";
         string lField2 = "name VARCHAR(40) NOT NULL,";
         string lField3 = "birthdate DATE,";
         string lKey = "PRIMARY KEY (id)";
         string lTableDefinition = lField1 + lField2 + lField3 + lKey;
         ExecuteNonQuery(lConnection, "DROP TABLE IF EXISTS test");               
         ExecuteNonQuery(lConnection, "CREATE TABLE test(" + lTableDefinition + ");");

         // fill the table with values
         ExecuteNonQueryAddRow(lConnection, "George Washington", new DateTime(1732, 2, 22));
         ExecuteNonQueryAddRow(lConnection, "Abraham Lincoln", new DateTime(1809, 2, 12));
         ExecuteNonQueryAddRow(lConnection, "Ronald Reagan", new DateTime(1911, 2, 6));
         ExecuteNonQueryAddRow(lConnection, "Bill Clinton", new DateTime(1946, 8, 19));

         // Query
         DataTable lTable = ExecuteQuery(lConnection, "SELECT * FROM test");
               
         // print column names
         foreach (DataColumn lColumn in lTable.Columns) Console.Write(lColumn.ColumnName + "; ");
         Console.WriteLine();

         // print rows
         int lColumnCount = lTable.Columns.Count;
         foreach (DataRow lRow in lTable.Rows) {
            for (int i = 0; i < lColumnCount; i++) {
               object o = lRow[i];
               if (o is DateTime) {
                  DateTime lDateTime = (DateTime)o;
                  Console.Write(lDateTime.ToString("dd MMM yyyy") + "; ");
                  continue;
               }                     
               Console.Write(o.ToString() + "; ");
            }
            Console.WriteLine();
         }

         // clean up
         ExecuteNonQuery(lConnection, "DROP TABLE IF EXISTS test");               
      }
   }
   catch (Exception ex) {
      Console.WriteLine(ex.Message + Environment.NewLine + ex.StackTrace);
   }
} //      
package Demos;

import java.sql.*;
import java.util.*;

public class MySqlDemo {

  public static Calendar getDate(int xYear, int xMonth, int xDay, int xHour, int xMinute, int xSecond) {
    Calendar lCalendar = Calendar.getInstance();
    lCalendar.clear();
    lCalendar.set(xYear, xMonth - 1, xDay, xHour, xMinute, xSecond);
    return lCalendar;
  } //

  private int ExecuteNonQuery(Connection xConnection, String xCommand) {
    Statement lStatement = null;
    try {
      lStatement = xConnection.createStatement();
      return lStatement.executeUpdate(xCommand);
    } catch (SQLException ex) {
      System.out.println("SqlException: " + ex.getMessage());
    } finally {
      CloseStatement(lStatement);
    }
    return -1;
  } //

  private void ExecuteNonQueryAddRow(Connection xConnection, String xName, Calendar xBirthday) {
    // old school
    //String lBirthday = String.format("%1$tY-%1$tm-%1$te", xBirthday);
    //String lCommand = String.format("INSERT INTO test (name, birthdate) values ('%s', '%s')", xName, lBirthday);
    //int lResult = ExecuteNonQuery(xConnection, lCommand);

    // modern school
    PreparedStatement lStatement = null;
    try {
      java.sql.Date lBirthday = new java.sql.Date(xBirthday.getTimeInMillis());
      lStatement = xConnection.prepareStatement("INSERT INTO test (name, birthdate) VALUES (?,?)");
      lStatement.setString(1, xName);
      lStatement.setDate(2, lBirthday, xBirthday);
      lStatement.executeUpdate();
    } catch (SQLException ex) {
      System.out.println("SqlException: " + ex.getMessage());
    } finally {
      CloseStatement(lStatement);
    }
  } //

  private void CloseStatement(Statement xStatement) {
    if (xStatement == null) return;

    try {
      xStatement.close();
    } catch (SQLException ex) {
      System.out.println("SqlException: " + ex.getMessage());
    }
  } //

  private void CloseStatement(PreparedStatement xStatement) {
    if (xStatement == null) return;

    try {
      xStatement.close();
    } catch (SQLException ex) {
      System.out.println("SqlException: " + ex.getMessage());
    }
  } //

  private void CloseResultSet(ResultSet xResultSet) {
    if (xResultSet == null) return;

    try {
      xResultSet.close();
    } catch (SQLException ex) {
      System.out.println("SqlException: " + ex.getMessage());
    }
  } //

  private void ExecuteQuery(Connection xConnection, String xCommand) {
    ResultSet lResultSet = null;
    Statement lStatement = null;

    try {
      lStatement = xConnection.createStatement();
      lResultSet = lStatement.executeQuery(xCommand);

      // print column headers
      ResultSetMetaData lMetaData = lResultSet.getMetaData();
      for (int i = 1, n = lMetaData.getColumnCount(); i <= n; i++)
        System.out.print(lMetaData.getColumnLabel(i) + " ");
      System.out.println();

      // print data
      while (lResultSet.next()) {
        long lId = lResultSet.getLong(1);
        String lName = lResultSet.getString(2);
        java.sql.Date lBirthday = lResultSet.getDate(3);
        System.out.println(lId + ": " + lName + " was born on " + lBirthday.toString());
      }
    } catch (SQLException ex) {
      System.out.println("SqlException: " + ex.getMessage());
    } finally {
      CloseStatement(lStatement);
      CloseResultSet(lResultSet);
    }
  } //

  public final void MySqlConnectionTest() {
    String lIpAddress = "127.0.0.1:3306";
    String lDatabase = "ohta";
    String lUser = "root";
    String lPassword = "root";

    Connection lConnection = null;
    try {
      Class.forName("com.mysql.jdbc.Driver");
      System.out.println("driver connection successful");

      String lUrl = "jdbc:mysql://" + lIpAddress + "/" + lDatabase;
      lConnection = DriverManager.getConnection(lUrl, lUser, lPassword);
      System.out.println("database connection successful");

      // create a new table
      String lField1 = "id INT  NOT NULL AUTO_INCREMENT,";
      String lField2 = "name VARCHAR(40) NOT NULL,";
      String lField3 = "birthdate DATE,";
      String lKey = "PRIMARY KEY (id)";
      String lTableDefinition = lField1 + lField2 + lField3 + lKey;

      ExecuteNonQuery(lConnection, "DROP TABLE IF EXISTS test");
      ExecuteNonQuery(lConnection, "CREATE TABLE test(" + lTableDefinition + ");");

      // fill the table with values
      ExecuteNonQueryAddRow(lConnection, "George Washington", getDate(1732, 2, 22, 0, 0, 0));
      ExecuteNonQueryAddRow(lConnection, "Abraham Lincoln", getDate(1809, 2, 12, 0, 0, 0));
      ExecuteNonQueryAddRow(lConnection, "Ronald Reagan", getDate(1911, 2, 6, 0, 0, 0));
      ExecuteNonQueryAddRow(lConnection, "Bill Clinton", getDate(1946, 8, 19, 0, 0, 0));

      // Query
      ExecuteQuery(lConnection, "SELECT * FROM test");

      // clean up
      ExecuteNonQuery(lConnection, "DROP TABLE IF EXISTS test");

    } catch (ClassNotFoundException ex) {
      System.out.println("ClassNotFoundException: " + ex.getMessage());
    } catch (SQLException ex) {
      System.out.println("SqlException: " + ex.getMessage());
    } finally {
      if (lConnection != null) try {
        lConnection.close();
      } catch (SQLException ex) {
        System.out.println("SqlException: " + ex.getMessage());
      }
    }
  } //

  public static void main(String[] args) {
    MySqlDemo lDemo = new MySqlDemo();
    lDemo.MySqlConnectionTest();
  } //

} // class
// .h file
#pragma once

#include <stdlib.h>
#include <iostream>
#include "mysql_connection.h"
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>

using namespace std;
using namespace sql;

class Day6 {
private:
  void ExecuteNonQuery(Statement * const xStatement, const string &xCommand);
  void ExecuteNonQueryAddRow(PreparedStatement *xPreparedStatement, const string &xName, const int &xYear, const int &xMonth, const int &xDay); 
  ResultSet *ExecuteQuery(Connection *xConnection, const string &xCommand);  
public:
  int test(void);
};

// .cpp file
#include "stdafx.h"
#include "Day6.h"

void Day6::ExecuteNonQuery(Statement * const xStatement, const string &xCommand) {
  SQLString lCommand(xCommand);
  xStatement->execute(lCommand);
} //

void Day6::ExecuteNonQueryAddRow(PreparedStatement *xPreparedStatement, const string &xName, const int &xYear, const int &xMonth, const int &xDay) {
  SQLString lName(xName);
  xPreparedStatement->setString(1, lName);
  int64_t lBirthday = xYear * 10000 + xMonth * 100 + xDay;
  xPreparedStatement->setInt64(2, lBirthday);
  xPreparedStatement->executeUpdate();
} //

ResultSet *Day6::ExecuteQuery(Connection *xConnection, const string &xCommand) {
  SQLString lCommand(xCommand);
  PreparedStatement *lPreparedStatement = xConnection->prepareStatement(lCommand);
  ResultSet *lResultSet = lPreparedStatement->executeQuery();
  delete lPreparedStatement;
  return lResultSet;
} //

int Day6::test(void) {
  try {
    // connect
    Driver *lDriver = get_driver_instance();
    Connection *lConnection = lDriver->connect("tcp://127.0.0.1:3306", "root", "root");

    // lConnection->setAutoCommit(0); // turn off auto commit        
    lConnection->setSchema("ohta"); // replace it with your database name

    // create a new table
    string lField1 = "id INT NOT NULL AUTO_INCREMENT,";
    string lField2 = "name VARCHAR(40) NOT NULL,";
    string lField3 = "birthday INT,";  // YYYYMMDD
    string lKey = "PRIMARY KEY (id)";
    string lTableDefinition = lField1 + lField2 + lField3 + lKey;
    string lCommand = "CREATE TABLE test(" + lTableDefinition; lCommand += ")";

    Statement *lStatement = lConnection->createStatement();

    ExecuteNonQuery(lStatement, "DROP TABLE IF EXISTS test");    
    ExecuteNonQuery(lStatement, lCommand);
    delete lStatement;

    // fill the table with values
    PreparedStatement *lPreparedStatement = lConnection->prepareStatement("INSERT INTO test (name, birthday) values (?, ?)");
    ExecuteNonQueryAddRow(lPreparedStatement, "George Washington", 1732, 2, 22);
    ExecuteNonQueryAddRow(lPreparedStatement, "Abraham Lincoln", 1809, 2, 12);
    ExecuteNonQueryAddRow(lPreparedStatement, "Ronald Reagan", 1911, 2, 6);
    ExecuteNonQueryAddRow(lPreparedStatement, "Bill Clinton", 1946, 8, 19);
    delete lPreparedStatement;

    // Query
    ResultSet *lResultSet = ExecuteQuery(lConnection, "SELECT * FROM test;");

    // print column names    
    ResultSetMetaData *lMeta = lResultSet->getMetaData();
    unsigned int lColumnCount = lMeta->getColumnCount();
    for (unsigned int i = 1; i <= lColumnCount; i++) {
     SQLString lColumnName = lMeta->getColumnName(i);  // http://bugs.mysql.com/bug.php?id=70006
     SQLString lTypeName = lMeta->getColumnTypeName(i);
     cout << lColumnName.asStdString() << ": " << lTypeName.asStdString() << endl;
    }    

    // print rows    
    lResultSet->beforeFirst();    
    while (lResultSet->next()) {
      string lId = to_string(lResultSet->getInt("id"));
      SQLString h = lResultSet->getString("name"); // http://bugs.mysql.com/bug.php?id=70006      
      const string lName = h.asStdString();
      int64_t lBirthday = lResultSet->getInt("birthday");
      int lYear = (int)( lBirthday / 10000);
      int lMonth = (int)(lBirthday % 10000) / 100;
      int lDay = (int)(lBirthday % 100);

      cout << lId << ", " << lName << ", " << lYear << "/" << lMonth << "/" << lDay << endl;      
    }

    // clean up
    lStatement = lConnection->createStatement();
    ExecuteNonQuery(lStatement, "DROP TABLE IF EXISTS test");

    delete lStatement;
    delete lResultSet;
    lConnection->close();
    delete lConnection;
  }
  catch (SQLException &e) {
    cout << "exception" << e.getSQLState() << endl;
  }

  return EXIT_SUCCESS;
}

migration C#, Java, C++ (day 5), lambda and TBB

logo

Phew, this was a terrible day. I wanted to do far more, but I had realized that there is no proper native threading in the C++ standard libraries. Back in the 1990s threading was a minor issue. We only had one CPU and FPU. We were concentrating more on the processes and devices at that time.

I had already mentioned that I wanted to avoid Boost and Qt. The best option I found was TBB, which seems to support multicore-processors very well. I will include TBB in my migration project from now on. Today, there is only one TBB example. It took me a lot of time to get the Intel software installed on my PC.

Finally, after all these years … we can solve problems with PCs that we would not have without them 😉

TBB covers only a small fraction today. This post is mainly about lambda functions.
In C++ you can find a lot of weird stuff that has been solved in a much better way in C#. As a hardcore C# programmer C++ might feel medieval sometimes. Rome was built bit by bit. Hence its streets are chaotic. C# maybe is like Chicago. When the city was built, people had time to think about the infrastructure before they started digging arbitrary holes in the ground.
Let’s see what my thoughts will be on day 15.

Please also check my post Lambda expressions (advanced). I mentioned that the C# compiler takes care of the local variable life-cycles, when lambda expressions use local variables, which would become invalid by the time these expressions try to use them. Remember, these local variables are not created inside the lambda expressions themselves.

Today’s prerequisite for C++

#include <iostream>
#include <vector>
#include <ctime>
#include <thread>
#include "tbb/tbb.h"
#include "tbb/parallel_for.h"
using namespace std;

Lambda

public void DoSomething() {
   Console.WriteLine(Thread.CurrentThread.ManagedThreadId + " ");
   Thread.Sleep(200);
} //

public void Lambdas() {
   // functor
   // There are no functors in C#.
   // Action or Func delegates are the closest approaches.
   Action lAction = DoSomething;
   lAction();

   // lambda expression
   Func<int, int> func2 = (int x) => { return ++x; };
   int r2 = func2(4);
   Console.WriteLine(r2); // 5

   // lambda expression capturing a local variable
   // the compiler takes care of the lifetime of variable i
   int i = 5;
   Func<int, int> func3 = (int x) => { return x + i; };
   int r3 = func3(4);
   Console.WriteLine(r3); // 9

   // lambda expression capturing any local variable by reference
   List<int> lList = new List<int>() { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23 };
   int lSum1 = 0;
   lList.ForEach((int q) => { lSum1 += q; });
   Console.WriteLine(lSum1); // 101

   // lambda expression with a specific return type
   Func<int, bool> func6 = (int x) => { x++; return true; };
   bool r6 = func6(4);
   Console.WriteLine(r6); // True
} //
class Class1 implements Runnable {
  @Override
  public void run() {
    try {
      System.out.println(Thread.currentThread().getId() + " ");
      Thread.sleep(200);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
} // class

public static void main(String[] args) {
    Class1 c1 = new Class1();
    c1.run();

    // lambda expression
    Function<Integer, Integer> func2 = i -> { return ++i; };
    Integer r2 = func2.apply(4);
    System.out.println(r2); // 5

    // lambda expression capturing a local variable
    // the compiler takes care of the lifetime of variable i
    Integer i = 5;
    Function<Integer, Integer> func3 = x -> { return x + i; };
    int r3 = func3.apply(4);
    System.out.println(r3); // 9

    // lambda expression capturing any local variable by reference
    java.util.ArrayList<Integer> lList = new java.util.ArrayList<>(java.util.Arrays.asList(new Integer[]{1, 2, 3, 5, 7, 11, 13, 17, 19, 23}));
    Integer lSum1 = 0;
    lList.forEach((Integer q) -> {
      //lSum1 += q;  compiler complains, because it has no write access to lSum1
    });
    // thus we have to use:
    lSum1 = lList.stream().map((q) -> q).reduce(lSum1, Integer::sum);
    System.out.println(lSum1); // 101 

    // lambda expression with a specific return type
    Function<Integer, Boolean> func6 = x -> {
      x++;
      return true;
    };
    boolean r6 = func6.apply(4);
    System.out.println(r6); // true
  } // 
class func1 {
public:
  int operator ()(int x) { return ++x; }
};

void Lambdas() {

  // functor
  int r1 = func1()(3);
  cout << r1 << endl; // 4

  // lambda expression
  auto func2 = [](int x) { return ++x; };
  int r2 = func2(4);
  cout << r2 << endl; // 5

  // lambda expression capturing a local variable
  int i = 5;
  auto func3 = [i](int x) { return x + i; };
  int r3 = func3(4);
  cout << r3 << endl; // 9

  // lambda expression capturing any local variable
  auto func4 = [=](int x) { return x + i + r2 * r1; };  // 1 + 5 + (5 * 4)
  int r4 = func4(1);
  cout << r4 << endl; // 26

  // lambda expression capturing a local variable by reference
  vector<int> v1{ 1, 2, 3, 5, 7, 11, 13, 17, 19, 23 };
  int lSum1 = 0;
  for (int q : v1) { [&lSum1](int x) {lSum1 += x; } (q); }
  cout << lSum1 << endl; // 101

  // lambda expression capturing any local variable by reference
  vector<int> v2{ 1, 2, 3, 5, 7, 11, 13, 17, 19, 23 };
  int lSum2 = 0;
  int lProduct2 = 1;
  for (int q : v2) { [&](int x) {lSum2 += x; lProduct2 *= x; }(q); }
  cout << lSum2 << " " << lProduct2 << endl; // 101 223092870

  // lambda expression capturing any local variable by value
  // The external variables can be assigned, but they are not referenced,
  // because the lambda expression is only working with local copies.
  // This can be achieved by using the keyword "mutable".
  // By default lambdas are not mutable.
  int lSum3 = 0;
  int lProduct3 = 1;
  auto func5 = [=](int x) mutable {lSum3 += x; lProduct3 *= x; return x; };
  int r5 = func5(1);
  cout << lSum3 << " " << lProduct3 << " " << r5 << endl; // 0 1 1

  // lambda expression with a specific return type
  auto func6 = [](int x) -> bool { x++; return true; };
  bool b6 = func6(6);
  cout << (b6 ? "true" : "false") << endl; // true
} //

TBB

public void TBB() {
  const int lSize = 100;

  Stopwatch lStopwatch = new Stopwatch();
  lStopwatch.Start();
  for (int i = 0; i < lSize; i++) DoSomething();
  lStopwatch.Stop();
  Console.WriteLine();
  Console.WriteLine("time for serial loop was " + lStopwatch.ElapsedMilliseconds / 1000.0 + " seconds");

  lStopwatch.Reset();
  lStopwatch.Start();
  Parallel.For(0, lSize, i => DoSomething());
  lStopwatch.Stop();
  Console.WriteLine();
  Console.WriteLine("time for parallel loop was " + lStopwatch.ElapsedMilliseconds/1000.0 + " seconds");
} //

example output:
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9
time for serial loop was 20.001 seconds
9 10 11 13 14 12 15 17 16 9 10 11 13 14 12 15 17 16 9 10 11 13 14 12 15 17 16 9
10 11 13 14 12 15 17 16 9 10 11 13 14 12 15 17 16 9 10 11 13 14 12 15 17 16 9 10
11 13 14 12 15 17 16 9 10 11 13 14 12 15 16 9 10 11 13 14 12 15 16 9 10 11 13 1
4 12 15 9 10 11 13 14 12 15 9 10 11 13 14 12 15
time for parallel loop was 2.408 seconds

public final void TBB() {
  Class1 lDoSomething = new Class1();
  final int lSize = 100;

  long lStopwatch = System.currentTimeMillis();
  for (int i = 0; i < lSize; i++) {
    lDoSomething.run();
  }
  long lDiff = System.currentTimeMillis() - lStopwatch;
  System.out.println();
  System.out.println("time for serial loop was " + lDiff / 1000 + " seconds");

  lStopwatch = System.currentTimeMillis();    
  ArrayList<Class1> lList = new ArrayList<>();
  for (int i = 0; i < lSize; i++) lList.add(lDoSomething);
  lList.parallelStream().forEach(x -> x.run());

  lDiff = System.currentTimeMillis() - lStopwatch;
  System.out.println();
  System.out.println("time for parallel loop was " + lDiff / 1000.0 + " seconds");
} //

example output:
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
time for serial loop was 20 seconds
12 13 14 1 16 11 15 17 14 13 12 1 16 11 15 17 13 12 14 1 16 17 11 15 13 14 12 16 1 11 15 17 13 14 12 16 1 11 15 17 12 13 14 1 16 11 17 15 14 12 13 16 1 15 17 11 12 13 14 16 1 17 11 15 14 13 12 1 16 11 15 17 13 14 12 1 16 15 17 11 14 12 13 16 1 11 17 15 14 12 13 16 1 17 11 15 12 13 1 15
time for parallel loop was 2.841 seconds

void DoSomething() {
  cout << this_thread::get_id() << "  ";
  this_thread::sleep_for(chrono::milliseconds(200));
} //

void TBBs() {
  const int lSize = 100;

  time_t lTimer;
  time(&lTimer);
  for (int i = 0; i < lSize; i++) DoSomething();
  double lSecondsA = difftime(time(nullptr), lTimer);
  cout << endl << "time for serial loop was " << lSecondsA << " seconds" << endl;

  time(&lTimer);
  tbb::parallel_for(0, lSize, 1, [&](int i) {	DoSomething(); });
  double lSecondsB = difftime(time(nullptr), lTimer);
  cout << endl << "time for parallel loop was " << lSecondsB << " seconds" << endl;
} //

example output:
4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 46
16 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616
4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616
4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 46
16 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616
4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616
4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 4616 46
16 4616 4616 4616 4616 4616 4616
time for serial loop was 20 seconds
4616 4068 4916 3788 2880 4168 4752 6796 4616 4916 4068 2880 3788 41
68 6796 4752 4616 4068 4916 2880 3788 4168 6796 4752 4616 4916 4068
2880 3788 4168 6796 4752 4616 4916 4068 3788 2880 4168 6796 4752
4616 4068 4916 2880 3788 4168 6796 4752 4616 4068 4916 3788 2880 41
68 6796 4752 4616 4068 4916 2880 3788 6796 4168 4752 4616 4068 4916
2880 3788 6796 4168 4752 4616 4068 4916 2880 3788 6796 4168 4752
4616 4916 4068 3788 2880 6796 4168 4752 4616 4068 4916 3788 2880 67
96 4168 4752 4616 4916 4068 3788
time for parallel loop was 2 seconds

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

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

logo

Containers in C++ are like C# collections.
The sequential containers are vector, deque and list. The latter is by far the slowest one. List comes close to LinkedList in C#. Vector and deque are like Lists in C#.

Available Methods:

vector deque list
similar in C# List List LinkedList
front(), back() yes yes yes
push_back(), pop_back() yes yes yes
push_front(), pop_front() no yes yes
at(), operator [] yes yes no
#include <iostream>
#include <string>
#include <list>
#include <algorithm>
#include <vector>
#include <deque>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <memory>

LinkedList

LinkedList<string> lLinkedList = new LinkedList<string>();
LinkedListNode<string> lLast = lLinkedList.AddLast("Last");
LinkedListNode<string> lFirst = lLinkedList.AddFirst("First");
LinkedListNode<string> lMid = lLinkedList.AddAfter(lFirst, "Mid");
bool b1 = lLinkedList.Contains("Last");
LinkedListNode<string> lFind = lLinkedList.Find("Last");
lLinkedList.Remove("First");
lLinkedList.RemoveFirst();
lLinkedList.Remove(lLast);
lLinkedList.Clear();
java.util.LinkedList<String> lLinkedList = new java.util.LinkedList<String>();
lLinkedList.addLast("Last");
lLinkedList.addFirst("First");
lLinkedList.add(1, "Mid");
boolean b1 = lLinkedList.contains("Last");
int lFind = lLinkedList.indexOf("Last");
//lLinkedList.remove(lFind);
lLinkedList.remove("First");
lLinkedList.removeFirst();
lLinkedList.removeLast();
lLinkedList.clear();
list<string> lLinkedList = list<string>();
lLinkedList.push_back("Last");
lLinkedList.push_front("First");
list<string>::iterator lIterator = lLinkedList.begin();
lIterator++;
lLinkedList.insert(lIterator, "Mid1");
lLinkedList.insert(lIterator, "Mid2");
cout << "List: " << endl;
for (lIterator = lLinkedList.begin(); lIterator != lLinkedList.end(); lIterator++)
	cout << *lIterator << " ";	//List:	First Mid1 Mid2 Last

lLinkedList.remove("First");
lLinkedList.pop_front();
lLinkedList.remove("Mid2");
cout << endl << endl << "List: " << endl;
for (lIterator = lLinkedList.begin(); lIterator != lLinkedList.end(); lIterator++)
	cout << *lIterator << " ";	//List: Last

lLinkedList.clear();

List

List<string> lList = new List<string>();
lList.Add("First");
lList.AddRange(new string[] { "Mid1", "Last" });
bool b2 = lList.Contains("Mid1");
lList.Insert(2, "Mid2"); // First, Mid1, Mid2, Last
lList.Reverse(); // Last, Mid2, Mid1, First
lList.Sort(); // First, Last, Mid1, Mid2
string[] lStringArray = lList.ToArray();
lList.Clear();
java.util.ArrayList<String> lList = new java.util.ArrayList<String>();
lList.add("First");
lList.addAll(Arrays.asList("Mid1", "Last"));
boolean b2 = lList.contains("Mid1"); // true
lList.add(2, "Mid2"); // First, Mid1, Mid2, Last
java.util.Collections.reverse(lList); // Last, Mid2, Mid1, First
java.util.Collections.sort(lList); // First, Last, Mid1, Mid2
String[] lStringArray = lList.toArray(new String[0]);
lList.clear();
inline bool MyDataSortPredicate(const string &s1, const string &s2) { return s1 < s2; }

vector<string> lList = vector<string>();
lList.push_back("First");
string lArray[] {lList.front(), "Mid", "Last"};
lList.assign(lArray, lArray + 3);
lList.push_back("VeryLast"); // First, Mid, Last, VeryLast
reverse(lList.begin(), lList.end()); // VeryLast, Last, Mid, First
sort(lList.begin(), lList.end(), MyDataSortPredicate); // First, Last, Mid, VeryLast
string *lStringArray = lList.data();
lStringArray++;
string lResult = lStringArray[1]; // Mid
lList.clear();

deque<string> lList2 = deque<string>();
lList2.push_back("First");
string lArray2[] {lList2.front(), "Mid", "Last"};
lList2.assign(lArray2, lArray2 + 3);	
auto lIterator2 = lList2.end();
lIterator2--;
lList2.emplace(lIterator2, "Mid2");
lList2.push_back("VeryLast"); // First, Mid, Mid2, Last, VeryLast
reverse(lList2.begin(), lList2.end()); // VeryLast, Last, Mid2, Mid, First
sort(lList2.begin(), lList2.end(), MyDataSortPredicate); // First, Last, Mid, Mid2, VeryLast	
lList2.clear();

Collections comparison

// key value pairs (no duplicate keys)
Dictionary<string, string> lDictionary = new Dictionary<string, string>(); // uses a hashmap
SortedDictionary<string, string> lSortedDictionary = new SortedDictionary<string, string>(); // uses a binary tree
SortedList<string, string> lSortedList = new SortedList<string, string>(); // uses arrays

// lists
List<string> lList3 = new List<string>(); // duplicate entries allowed
HashSet<string> lHashSet = new HashSet<string>(); // a List with no duplicates entries; behaves like a Dictionary with key==value
SortedSet<string> lSortedSet = new SortedSet<string>(); // a sorted list with no duplicates; behaves like a SortedDictionary with key==value
// key value pairs (no duplicate keys)
java.util.HashMap<String, String> lDictionary = new java.util.HashMap<String, String>();
java.util.TreeMap<String, String> lSortedDictionary = new java.util.TreeMap<String, String>();
// There is no such as a SortedList in Java

// lists
java.util.ArrayList<String> lList3 = new java.util.ArrayList<String>();
java.util.HashSet<String> lHashSet = new java.util.HashSet<String>();
java.util.TreeSet<String> lSortedSet = new java.util.TreeSet<String>();
// key value pairs (no duplicate keys)
unordered_map<string, string> lDictionary = unordered_map<string, string>(); // uses a hashmap
map<string, string> lSortedDictionary = map<string, string>(); // uses a binary tree
// lSortedList = no equivalent 

// lists
vector<string> lList2 = vector<string>(); // duplicate entries allowed
unordered_set<string> lHashSet = unordered_set<string>(); // a List with no duplicates entries; behaves like a Dictionary with key==value
set<string> lSortedSet = set<string>(); // a sorted list with no duplicates; behaves like a SortedDictionary with key==value

Threading

void f1() {
   Thread.Sleep(500);
   Console.WriteLine("f1 says: Hello world!");
}

void f2(object o) {
   Thread.Sleep(1000);
   string s;
   if (o is string) s = o as string;
   else {
      // for sure using a "volatile" variable in a class as storage would be a better approach
      string[] h = (string[])o;
      s = h[0];
      h[0] = "new Message";
   }
   Console.WriteLine("f2 says: " + s);
}


Console.WriteLine("The parent thread id is: " + Thread.CurrentThread.ManagedThreadId);

Thread t1 = new Thread(f1); // "f1 says: Hello world!"
t1.IsBackground = true; // not the same as daemon! It is a background thread that is dependent from the main thread.
t1.Start();
t1.Join();

string lByVal = "Agent Smith is everywhere :(";
Thread t2 = new Thread(f2); // "f2 says: Agent Smith is everywhere :("
t2.Start(lByVal);

string[] lByRef = { "Agent Smith is everywhere :(" };
Thread t3 = new Thread(f2); // "f2 says: Agent Smith is everywhere :("
t3.Start(lByRef);
t3.Join();
Console.WriteLine("same text? " + lByRef[0]); // "same text? new Message"         
class Class1 implements Runnable {
  @Override
  public void run() {
    try { Thread.sleep(500); }
    catch (InterruptedException e) { e.printStackTrace(); }
    System.out.println("c1 says: Hello world!");      
    }
 } // class

class Class2 implements Runnable {
  private Object _Parameter;

  public Class2(Object xParameter) {
    _Parameter = xParameter;
  } // constructor
  
  public void run() {
    try { Thread.sleep(1000); }
    catch (InterruptedException e) { e.printStackTrace(); }
    String s;
    if (_Parameter instanceof String) s = (String)_Parameter;
    else {
       String[] h = (String[])_Parameter;
       s = h[0];
       h[0] = "new Message";
    }
    System.out.println("c2 says: " + s);   
  } //
} // class

System.out.println("The parent thread id is: " + Thread.currentThread().getId());

Class1 lInstance1 = new Class1();
Thread t1 = new Thread(lInstance1); // "c1 says: Hello world!"
t1.setDaemon(true); 
t1.start();
try { t1.join(); }
catch (InterruptedException e) { e.printStackTrace(); }

String lByVal = "Agent Smith is everywhere :(";
Class2 lInstance2 = new Class2(lByVal);   
Thread t2 = new Thread(lInstance2); // "c2 says: Agent Smith is everywhere :("
t2.start();

String[] lByRef = {"Agent Smith is everywhere :("};
Class2 lInstance3 = new Class2(lByRef);
Thread t3 = new Thread(lInstance3); // "c2 says: Agent Smith is everywhere :("
t3.start();
try { t3.join(); }
catch (InterruptedException e) { e.printStackTrace(); }
System.out.println("same text? " + lByRef[0]); // "same text? new Message"
void f1() {
	this_thread::sleep_for(chrono::milliseconds(500));
	cout << "f1 says: Hello world!" << endl;
}

void f2(string xMessage) {
	this_thread::sleep_for(chrono::milliseconds(1000));
	cout << "f2 says: " << xMessage << endl;
}

class f3 {
public:
	void operator()(string &xMessage) { 
		this_thread::sleep_for(chrono::milliseconds(1500));
		cout << "functor f3 says: " << xMessage << endl; 
		xMessage = "new Message";
	}
};

cout << "The parent thread id is: " << this_thread::get_id() << endl;

thread t1(f1); // "f1 says: Hello world!"
t1.detach(); // t1 becomes a daemon process (background + no terminal)
if (t1.joinable()) t1.join(); // joinable() returns false

thread t2(f2, "Mr Anderson is Neo."); // "f2 says: Mr Anderson is Neo."
string lByValue = "Agent Smith is everywhere :(";
thread t3((f3()), lByValue); // functor f3 says: Agent Smith is everywhere :("

t2.join();
t3.join();

cout << "same text? " << lByValue << endl;  // "same text? Agent Smith is everywhere :("
	
string lByRef = lByValue;
thread t4((f3()), ref(lByRef));  // "functor f3 says: Agent Smith is everywhere :("
	
// so that the call by reference can assign a new value
// play with this value
t4.join(); 

cout << "same text? " << lByRef << endl;  // "same text? new Message"

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

logo

 

Day 2. I feel some heat already 😉

 

managed code

public class Dog {
   public string Name { get; set; }

   public Dog() { }
   public Dog(string xName) { Name = xName; }
}

// --------------------------------------------------------------

{
   Dog lDog1 = new Dog();
   Dog lDog2 = new Dog();
   lDog1 = null;  // allows the garbage collector to collect lDog1
} // leaving the scope allows lDog2 to be collected
public class Dog {
  public Dog() {}
  public Dog(String xName) { setName(xName); }

  private String _Name;
  public final String getName() { return _Name; }
  public final void setName(String value) { _Name = value; }
} // class

// --------------------------------------------------------------

{
  Dog lDog1 = new Dog();
  Dog lDog2 = new Dog();
  lDog1 = null; // allows the garbage collector to collect lDog1
} // leaving the scope allows lDog2 to be collected
// .h file
#ifndef DOG_H
#define DOG_H

#include <string>
#include <memory>

using namespace std;

class Dog : public enable_shared_from_this<Dog> {
private:
   string pName;
public:
  const string &getName() const;
  void setName(const string &xName);

  Dog();
  Dog(const string &xName);
};

#endif // DOG_H

// .cpp file

#include "Dog.h"

using namespace std;

Dog::Dog(){}
Dog::Dog(const string &xName) { setName(xName); }

const string &Dog::getName() const { return pName;}
void Dog::setName(const string &value) { pName = value; }


// --------------------------------------------------------------

shared_ptr<Dog> lDog1 (new Dog("Snoopy"));
cout<<lDog1.use_count() << endl; // 1
shared_ptr<Dog> lDog2 = make_shared<Dog>("Lassie");
cout<<lDog2.use_count() << endl; // 1
shared_ptr<Dog> lDog3 = lDog2;
cout<<lDog1.use_count() << endl; // 1
cout<<lDog2.use_count() << endl; // 2
cout<<lDog3.use_count() << endl; // 2

Dictionary

Dictionary<string, Double> lDictionary = new Dictionary<string, double>();
lDictionary.Add("-10-", 10.0);
lDictionary.Add("-20-", 20.0);
lDictionary.Add("-30-", 30.0);
lDictionary.Add("-40-", 40.0);
lDictionary.Remove("-30-");

foreach (var lPair in lDictionary) Console.WriteLine(lPair.Key + " equals " + lPair.Value);

foreach (var lValue in lDictionary.Values) Console.WriteLine(lValue);

Double d;
if (lDictionary.TryGetValue("-10-", out d)) Console.WriteLine("found -10- which is: " + d);
java.util.HashMap<String, Double> lDictionary = new java.util.HashMap<String, Double>();
lDictionary.put("-10-", 10.0);
lDictionary.put("-20-", 20.0);
lDictionary.put("-30-", 30.0);
lDictionary.put("-40-", 40.0);
lDictionary.remove("-30-");
// C# var: There is no such as implicit typing in Java
for (Entry<String, Double> lPair : lDictionary.entrySet()) System.out.println(lPair.getKey() + " equals " + lPair.getValue());
for (Double lValue : lDictionary.values()) System.out.println(lValue);

double d = 0;
if (lDictionary.containsKey("-10-") ? (d = lDictionary.get("-10-")) == d : false) System.out.println("found -10- which is: " + d);
unordered_map<string, double> lMap = unordered_map<string, double>();
lMap.insert(make_pair("-10-", 10.0));
lMap.insert(make_pair("-20-", 20.0));
lMap.insert(make_pair("-30-", 30.0));
lMap.insert(make_pair("-40-", 40.0));
lMap["-40-"] = 41.0;
lMap.erase("-30-");

for (auto &lPair : lMap) {
  cout << lPair.first << " equals " <<  lPair.second << endl;  // 10 20 41
}

double d1 = lMap["-10-"];	
cout << "found -10- which is: " << d1 << endl;	// 10.0
	
double d2 = lMap["-11-"];  // returns the default value
cout << "found -11- which is: " << d2 << endl; // 0.0

unordered_map<string, string> lMap2 = unordered_map<string, string>();	
lMap2["hello"] = "hulla";
string s = lMap2["hola"]; 
if (s == "") s = "EMPTY";
cout << "lMap2[\"hola\"] == " << s << endl; // s == "EMPTY"

Queue

Queue<Dog> lDogs = new Queue<Dog>();
lDogs.Enqueue(new Dog("Boomer"));
lDogs.Enqueue(new Dog("Spike"));
lDogs.Enqueue(new Dog("Lassie"));
Console.WriteLine(lDogs.Peek().Name); // Boomer
Dog lDog = lDogs.Dequeue();
Console.WriteLine(lDogs.Peek().Name); // Spike
// Queue is not a class, just an interface
java.util.Queue<Dog> lDogs = new java.util.LinkedList<Dog>();
lDogs.offer(new Dog("Boomer"));
lDogs.offer(new Dog("Spike"));
lDogs.offer(new Dog("Lassie"));
System.out.println(lDogs.peek().getName()); // Boomer
Dog lDog = lDogs.poll();
System.out.println(lDogs.peek().getName()); // Spike
#include <queue>

queue<Dog*> lDogs = queue<Dog*>();
lDogs.push(new Dog("Boomer"));
lDogs.push(new Dog("Spike"));
lDogs.push(new Dog("Lassie"));
cout << lDogs.front()->getName() << endl; // Boomer
cout << lDogs.back()->getName() << endl;  // Lassie
lDogs.pop(); // takes Boomer from the queue
cout << lDogs.front()->getName() << endl; // Spike
cout << lDogs.back()->getName() << endl;  // Lassie

Stack

Stack<Dog> lDogs = new Stack<Dog>();
lDogs.Push(new Dog("Boomer"));
lDogs.Push(new Dog("Spike"));
lDogs.Push(new Dog("Lassie"));
Console.WriteLine(lDogs.Peek().Name); // Lassie
Dog lDogLassie = lDogs.Pop();
Console.WriteLine(lDogs.Peek().Name); // Spike
java.util.Stack<Dog> lDogs = new java.util.Stack<Dog>();
lDogs.push(new Dog("Boomer"));
lDogs.push(new Dog("Spike"));
lDogs.push(new Dog("Lassie"));
System.out.println(lDogs.peek().getName()); // Lassie
Dog lDogLassie = lDogs.pop();
System.out.println(lDogs.peek().getName()); // Spike
stack<Dog*> lDogs = stack<Dog*>();
lDogs.push(new Dog("Boomer"));
lDogs.push(new Dog("Spike"));
lDogs.push(new Dog("Lassie"));
cout << lDogs.top()->getName() << endl; // Lassie
lDogs.pop(); // takes Lassie from the stack
cout << lDogs.top()->getName() << endl; // Spike

Generics, Templates

T larger<T>(T obj1, T obj2 ) {
   if ((dynamic)obj1 > (dynamic)obj2) return obj1;
   return obj2;
} //

int i = larger<int>(6, 4); // i == 6

bool same<T>(T obj1, T obj2 ) where T : class {
   return (obj1 == obj2);
} //

bool b1 = same<string>("ABC", "abc"); // False
bool b2 = same<string>("abc", "abc"); // True

public class MyClass<T, U> where T : struct where U : class {
   public T MyFunc(T a, U b, T c) {
      return c;
   }
}

MyClass<int, string> lClass = new MyClass<int, string>();
int i = lClass.MyFunc(0, "hello", 1); // i == 1
<T extends Comparable<T>> T larger(T obj1, T obj2) {
  if (obj1.compareTo(obj2) > 0) return obj1;
  return obj2;
}

int i = this.<Integer>larger(6, 4); // i == 6

<T extends Comparable<T>> boolean same(T obj1, T obj2) {
  return (obj1 == obj2);    
}

boolean b1 = this.<String>same("ABC", "abc"); // False
boolean b2 = this.<String>same("abc", "abc"); // True

class MyClass<T, U> {
  public final T MyFunc(T a, U b, T c) { return c; }
}

MyClass<Integer, String> lClass = new MyClass<Integer, String>();
int i = lClass.MyFunc(0, "hello", 1); // i == 1
template <typename T>
T larger(T obj1, T obj2){
    if(obj1 > obj2) return obj1;
    return obj2;
} //

int i = larger(6, 4); // i == 6

template <typename T>
bool same(T obj1, T obj2){
    if(obj1 == obj2) return true;
    return false;
} //

bool b1 = same("ABC", "abc"); // false
bool b2 = same("abc", "abc"); // true
bool b3 = same("abd", "abc"); // false    


template<typename T, typename U>
   class MyClass {
       U MyData;
public:
      T MyFunc(T a, U b, T c) { return c; }
      void MyFunc(int a, U b) { }
   };

MyClass<int, string> lClass;
int i = lClass.MyFunc(0, "hello", 1); // 1

simple Thread

No worries, there will be follow-ups.

private void MyThread(object x) {
  Console.WriteLine(x as string);
}

Thread lThread = new Thread(MyThread);
lThread.IsBackground = true;
lThread.Start("mySupaDupaaParameter");
public class MyThreadClass extends Thread {
  private String _Parameter;

  public MyThreadClass(String xParameter) {
    _Parameter = xParameter;
  } // constructor

  @Override
  public void run() {
    System.out.println(_Parameter);
  } //
} // class

MyThreadClass lInstance = new MyThreadClass("mySupaDupaaParameter");
Thread lThread = new Thread(lInstance);
lThread.setDaemon(true);
lThread.start();
#include <thread>

void MyThread(string xParameter) { cout << xParameter; }

thread lThread(MyThread, "mySupaDupaaParameter");

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

logo

This is day 1 of this series. I am covering some tricky basics between the two languages before we get more complicated. All should be self-explanatory. There is no clear structure yet. I just picked some examples that are worth mentioning.
There is a lot of code that cannot be written in C# or C++. Sometimes the differences are quite big. I am still trying to find a solution to show such properly in a comparison without just documenting each language by itself.

Arrays

// single-dimensional array
int[] a1 = new int[5];
Console.WriteLine(a1.Length); // 5

// rectangular array
int[,] a2 = new int[3, 4];
Console.WriteLine(a2.Length); // 12
Console.WriteLine(a2.GetUpperBound(0)); // 2
Console.WriteLine(a2.GetUpperBound(1)); // 3

// jagged arrays
int[][] a3 = new int[5][];
for (int i = 0, n = a3.Length; i < n; i++) a3[i] = new int[i + 3];
Console.WriteLine(a3.Length); // 5
Console.WriteLine(a3[3].Length); // 6
Console.WriteLine(a3.GetUpperBound(0)); // 4
// single-dimensional array
int[] a1 = new int[5];
System.out.println(a1.length); // 5

// rectangular array
int[][] a2 = new int[3][4];
System.out.println(a2.length); // 3
System.out.println(a2[0].length); // 4

// jagged arrays
int[][] a3 = new int[5][];
for (int i = 0, n = a3.length; i < n; i++) a3[i] = new int[i + 3];
System.out.println(a3.length); // 5
System.out.println(a3[3].length); // 6
// single-dimensional array
int* a0 = new int[5]; // Size cannot be determined. Use std::vector.

int a1[5];
cout << sizeof(a1) << endl;    // 20 bytes
cout << sizeof(a1)/sizeof(a1[0]) << endl;    // 5 elements

// rectangular array
unsigned int a2[3][4];
cout << "int[3][4]: " << sizeof(a2) << endl;    // 48
cout << "   int[4]: " << sizeof(*a2) << endl;   // 16
cout << "      int: " << sizeof(**a2) << endl;  // 4
cout << "       a2: " << a2 << endl;            // 0x28fed0
cout << "(*a2) + 1: " << (*a2) + 1 << endl;     // 0x28fed4 (4 higher)
cout << "   a2 + 1: " << a2 + 1 << endl;        // 0x28fee0 (16 higher)

// jagged arrays
int** a3 = new int*[5];
for(size_t i = 0; i < 5; ++i) a3[i] = new int[i + 3];
for(size_t i = 0; i < 5; ++i) delete[] a3[i];
delete[] a3;

Pointers

// call by reference vs. call by value
void CallByValue(int x) { x = 6; }
void CallByRefernce1(ref int x) { x = 1; }
void CallByRefernce2(out int x) { x = 2; }
public int func(int x) { return x; }

int h = 3;
CallByValue(h); Console.WriteLine(h); // 3
CallByRefernce2(out h); Console.WriteLine(h); // 2
CallByRefernce1(ref h); Console.WriteLine(h); // 1

// this is a simple delegate (not a pointer)
Func<int, int> f = func;
Console.WriteLine(f(5)); // 5
public final class delegateWrapper<T> {
  public T invoke(T t) {
    return t;
  }
} // class

public final class boxingWrapper<T> {
  public T value;

  public boxingWrapper(T xValue) {
    value = xValue;
  }
} // class

private void CallByValue(int x) { x = 6; }
private void CallByRefernce(boxingWrapper<Integer> x) { x.value = 1; }


int h = 3;
boxingWrapper<Integer> lWrapper = new boxingWrapper<Integer>(h);

CallByValue(h); // 3
System.out.println(h);
CallByRefernce(lWrapper);
h = lWrapper.value; // 1
System.out.println(h);

// there are no pointers or delegates in Java
delegateWrapper<Integer> lDelegate = new delegateWrapper<Integer>();
h = lDelegate.invoke(5);
System.out.println(h); // 5
// call by reference vs. call by value
void CallByValue(int x) { x = 6; }
void CallByRefernce(int &x) { x = 1; }
int func(int x) { return x; }

int h = 3;
CallByValue(h);    cout<<h<<endl; // 3
CallByRefernce(h); cout<<h<<endl; // 1

// pointer to a method
int (*f)(int) = 0;
f = &func;
cout<< f(5) << " " << (*f)(5) << endl; // 5 5

// pointer to integers (not available in C#)
int *p1;    // pointer to an integer
int p2[3];  // an array of 3 integers
int *p3[3]; // an array of 3 pointers to integers
int (*p4)[3]; // a pointer to an array of 3 integers
int *(&p5)[3] = p3; // a reference to an array of 3 pointers to integers
int *(*p6[3])[4]; // an array of 3 pointers to an array of 4 pointers to integers
int **(*p7[2])[3]; // an array of 2 pointers to an array of 3 pointers to pointers to integers

Strings

string s = "Hello World!"; // Unicode (24 bytes)
Console.WriteLine(s.Length); // 12
if (s.CompareTo("abc") > 0) Console.WriteLine("larger");

for (int i = 0, n = s.Length; i < n; i++) Console.Write(s[i] + " ");
Console.WriteLine();
foreach (char lChar in s) Console.Write(lChar + " ");
Console.WriteLine();

int lPosition = s.IndexOf("ll", 0);
s = s.Remove(lPosition, 2) + " / " + s.Substring(lPosition, 2);
Console.WriteLine(s);
String s = "Hello World!"; // Unicode (24 bytes)
System.out.println(s.length()); // 12
if (s.compareTo("abc") > 0) System.out.println("larger");

for (int i = 0, n = s.length(); i < n; i++) System.out.print(s.charAt(i) + " ");
System.out.println();
char[] lChars = s.toCharArray();
for (char lChar : lChars) System.out.print(lChar + " ");
System.out.println();

int lPosition = s.indexOf("ll", 0);
// there is no remove, so we need to simulate it
String h = s.substring(0, lPosition) + s.substring(lPosition + 2);
s = h + " / " + s.substring(lPosition, lPosition + 2);
System.out.println(s);
// strings (null terminated ASCII codes)
string s = "Hello World!";  // == {’H’, ’e’, ’l’, ’l’, ’o’, ’ ’, ’W’, ’o’, ’l’, ’d’, ’!’, ’\0’}
cout<< s << ", length: " << s.length() << endl;
cout<< sizeof(s) << endl; // pointer size
if (s < "abc") cout << "abc is larger" << endl; // operator overloaded in string.h

for (int i = 0;s[i] != '\0'; i++) cout << s[i] << " ";
cout << endl;
for (int i = 0, n = s.length(); i < n; i++) cout << s.at(i) << " "; // includes boundary checks and exception handling
cout << endl;
for (char &c : s) cout << c << " "; // includes boundary checks and exception handling
cout << endl;
int lPosition = s.find("ll", 0);
s = s.erase(lPosition, 2) + " / " + s.substr(lPosition, 2);
cout << s << endl;

// wstring holds unicode characters
// (wchar_t is 2 bytes on Windows, 4 bytes on Linux)
const wstring lWString = L"Hello wide world :)";
wcout<<lWString<<endl;  // direct output

string lString(lWString.begin(), lWString.end());
cout<<lString<<endl;

#define

// preprocessor #define is used to set flags
#if DEBUG
   Console.WriteLine("DEBUG CODE");
   try {
      throw new Exception();
   }
   catch (Exception ex) {
      Console.WriteLine(ex.StackTrace);
   }
#else
   Console.WriteLine("PROD CODE");
#endif
public static boolean DEBUG = true;

// There are no preprocessors in Java.
// To get as close as possible to the idea of preprocessors you
// can use public static variables or Dependency Injection.
public void test() {
  if (DEBUG) {
      System.out.println("DEBUG CODE");
      try {
        throw new RuntimeException();
      }
      catch (RuntimeException ex) {
        for (StackTraceElement x : ex.getStackTrace()) System.out.println(x.toString());
      }
  } else System.out.println("PROD CODE");
}
// preprocessor #define
#define OMG "Oh my god!\n"
cout << OMG << endl;

#define add(a, b, c) a + b + c + 1
cout << add(1, 2, 3) << endl; // 7

#define DEBUG
#ifdef DEBUG
    cout << "DEBUG CODE" << endl;
#else
    count << "PROD CODE" << endl;
#endif

cout << endl;
cout << "This is the line " << __LINE__ << " of file " << __FILE__ << endl;
cout << "Compilation date " << __DATE__ << " " << __TIME__ << endl;

struct vs. class

struct MyStruct { public double x; }  // value type
class MyClass { public double x; }    // reference type

MyStruct lStruct1 = new MyStruct();
MyStruct lStruct2 = lStruct1; // creates a copy of lStruct1
lStruct2.x = 1.0;
lStruct1.x = 99.9;
Console.WriteLine(lStruct2.x); // 1.0 !

MyClass lClass1 = new MyClass();
MyClass lClass2 = lClass1;  // only assigns the reference
lClass2.x = 1.0;
lClass1.x = 99.9;
Console.WriteLine(lClass2.x); // 99.9 !
// there are no user-defined value types like struct in Java
public class MyClass { public double x; }

private MyClass lClass1 = new MyClass();
private MyClass lClass2 = lClass1; // assigns the reference
lClass2.x = 1.0;
lClass1.x = 99.9;
System.out.println(lClass2.x); // 99.9
// Structs in C++ are like classes.
// The main difference is that the default for structs is public, whereas the default for classes is private.
// Some people say that structs are for data (no methods) only. This is not true. Both can have methods. 

Cast Operations

public class Dog { }
public class Husky : Dog { }
public class StyleGuide { }

// cast operations
double pi = 3.14159265;
int lInt = (int)pi;
double d = lInt;
Console.WriteLine(d); // 3.0

Dog lDog = new Husky();
Husky lHusky = lDog as Husky;
if (lHusky != null) Console.WriteLine("A husky is a dog");
StyleGuide lStyle = new StyleGuide();
//lHusky = (Husky)lStyle; //   won't compile
public class Dog { }
public class Husky extends Dog { }
public class StyleGuide { }

double pi = 3.14159265;
int lInt = (int)pi;
double d = lInt;
System.out.println(d); // 3.0

Dog lDog = new Husky();
Husky lHusky = (Husky)lDog;
if (lHusky != null) System.out.println("A husky is a dog");
StyleGuide lStyle = new StyleGuide();
// lHusky = (Husky)lStyle; //   won't compile
// cast operations
double pi = 3.14159265;
int    lInt = static_cast<int>(pi);
double d = lInt;
cout<<d<<endl; // 3.0

Dog *lDog = new Husky();
Husky *lHusky = dynamic_cast<Husky*>(lDog);
if (lHusky != 0) cout<<"A husky is a dog"<< endl;
StyleGuide *lStyle;
lHusky = dynamic_cast<Husky*>(lStyle);
if (lHusky == 0) cout<<"A StyleGuide is not a dog"<< endl;

const char* lConst = "Hello World";
char* lVariable = const_cast<char*>(lConst);

long lAddress = 5165786;
lDog = reinterpret_cast<Dog*>(lAddress);
if (lDog != 0) cout<<"What a funny dog"<< endl;

Collections:List

List<string> lList = new List<string>();
lList.Add("hello");
lList.Add("world");
foreach (var lItem in lList) Console.WriteLine(lItem);
lList.Clear();
lList = null;
java.util.ArrayList<String> lList = new java.util.ArrayList<String>();
lList.add("hello");
lList.add("world");
for (String lItem : lList) System.out.println(lItem);
lList.clear();
lList = null;
vector<wstring> lList = vector<wstring>();
lList.push_back(L"hello");
lList.push_back(L"world");
for (wstring &lItem : lList) wcout << lItem << endl;
lList.clear();

Our first class

using System;

namespace DemoApp.ToCpp {
   public class StyleGuide : IDisposable {

      private bool _Disposed = false;

      public StyleGuide() { }
      private double PrivateFunc(string s) { return 5.3; }
      public int PublicFunc(string s) { return 0; }
      protected string ProtectedFunc(string s) { return s; }

      ~StyleGuide() { Dispose(false); } // deconstructors call Finalize() of the base class

      public void Dispose() {
         Dispose(true);
         GC.SuppressFinalize(this);
      }

      protected virtual void Dispose(bool xDisposing) {
         if (_Disposed) return;
         if (xDisposing) {
            // free objects
         }
         _Disposed = true;
      } //

   } // class
} // namespace
package DemoApp.ToCpp;

public class StyleGuide {
  public StyleGuide() {}
  private double PrivateFunc(String s) { return 5.3; }
  public final int PublicFunc(String s) { return 0; }
  protected final String ProtectedFunc(String s) { return s; }

  @Override
  protected void finalize() throws Throwable {
    //
    // FreeResourcesHere();
    //
    super.finalize();
  } // destructor

} // class
#ifndef STYLEGUIDE_H
#define STYLEGUIDE_H

#include <iostream>
#include <string>

using namespace std;

class StyleGuide
{
    public:
        StyleGuide();
        virtual ~StyleGuide();
        int PublicFunc(string* s);
    protected:
        string ProtectedFunc(string* s);
    private:
        double PrivateFunc(string* s);
};

#endif // STYLEGUIDE_H
#include "StyleGuide.h"

StyleGuide::StyleGuide() {}

StyleGuide::~StyleGuide() {}

double StyleGuide::PrivateFunc(string *s) {
    return 5.3;
}

int StyleGuide::PublicFunc(string *s) {
    return 0;
}

string StyleGuide::ProtectedFunc(string *s) {
    return *s;
}