'Freiburg' and Threads

the Freiburg release 2.0 provides additional features including thread support.

1. What are Threads?

https://computing.llnl.gov/tutorials/pthreads/#Thread

2. Changes to Freiburg supporting Threads

thread support is available with a additional '-thread' option

using 'C' code

  // read command-line: -name MyApplication -thread
  MqBufferLSP argv = MqBufferLCreateArgv(NULL, --argc, ++argv);
  // using 'client' behavior (use MQ_SERVER for 'server')
  MqBufferLAppendH2(argv, "-type", MQ_CLIENT);
  // create the 'Freiburg' object
  MqErrorCheck(MqCreate(context, argv, &context->msgque));

3. what does '-thread' internal doing

Without thread support Freiburg is using one event-loop for serving multiple parent-context in a parallel manner. The main difference between an threaded application and an non-threaded application is the available of multiple control flows (e.g. main-loops). The -thread option changes the behaviour of Freiburg to use one event-loop per parent-context and is now able to serve multiple parent-context in different threads. Using multiple event-loops is slower than using one single event-loop. To avoid the overhead the -thread option is optional and only useful if multiple parent-context are used in different threads. If all parent-context reside in one thread the -tread may be safely ignored.

4. using Threads with tclFreiburg

tclFreiburg is using the tcl interpreter for command execution. The interpreter may be compiled with --enable-threads to use thread behavior. The -thread option is not available for Tcl because it is available by default in a tcl interpreter with thread support. The -nothread option is available to avoid the thread overhand.

5. example using Thread with tclFreiburg

This is an example using the aotto sort for sorting multiple integer values. The aotto sort creates for every integer value a thread and using Freiburg to call the TestFbg::EchoSleep service with 'integer' seconds. The goal is that short integer sleep short and long integer sleep long. The main procedure just waiting for every thread to finish. (this example is only usable for bio-informatics, but a good example using parallel behaviour)

 package require Thread
 set L1 {3 8 2 5 7 1 6 4 9}
 puts "1. create thread's ..."
 foreach I $L1 {
   lappend TH [thread::create]
 }
 puts "2. init thread's ..."
 foreach T $TH {
   thread::send $T {
   package require TestFbg
   set FH [TestFbg::Start -name Thread[thread::id] -debug 0]
   }
 }
 puts "3. waiting per thread ..."
 foreach I $L1 T TH {
   thread::send -async $T "TestFbg::EchoSleep \$FH $I" result
 }
 puts "4. wait on result ..."
 set RList [list]
 foreach I $L1 {
   vwait result
   lappend RList $result
 }
 puts "5. cleanup"
 foreach I $L1 T TH {
   thread::send $T {rename $FH ""}
   thread::release -wait $T
 }
 puts "6. finish"
 puts $RList