Hello again,
I am trying to add multi-threaded support for my application. I now face a problem witch combining XOTCl and Thread. The problem is that ::thread::create creates a new instance of interpreter which has own variables. I can have variables shared between threads using ::tsv functions. So here is how it looks:
1. Thread #1 creates object myObject and stores in a shared variable: ::tsv::set array1 key1 [MyClass myObject]
2. Thread #2 gets the shared variable and tries to call a proc defined for MyClass: set localVar [::tsv::get array1 key1] $localVar doSomething
At this point second thread will throw en exception saying: Unknown command 'myObject'
What would be the proper way to "register" the object myObject (which already exists) in another thread?
On 10.02.2011, at 14:27, Krzysztof Frukacz wrote:
What would be the proper way to "register" the object myObject (which already exists) in another thread?
No way. You need to ask Gustaf to give you serialisation-code that you can use to replicate your object/classes blueprints from one thread into others as a matter of thread inits. IIRC there must be a sample Serialize class somewhere in the distribution. Even then, an instantiated object cannot be shared/moved across threds. You need to instantiate it in the target thread.
Cheers Zoran
What would be the proper way to "register" the object myObject (which already exists) in another thread?
No way. You need to ask Gustaf to give you serialisation-code that you can use to replicate your object/classes blueprints from one thread into others as a matter of thread inits.
I can help out here: In order to serialize an object (in XOTcl, creating a canonical script from a in-memory snapshot of the given object, capable of creating an object and its dependencies with all the shebang), [package require] the serializer package which comes with your XOTcl distribution:
Class create C -slots { Attribute a1 -default aaa } -set x 1
C create c1
package req xotcl::serializer
# # this provides a new method to all ::xotcl::Object instances, i.e. all # objects -> serialize(): #
c1 serialize
-> ::C create ::c1 -noinit \ -set a1 aaa
the resulting script can be stored (e.g., in a tsv) and shared between thread interps. in the target interp, simply [eval] the script.
//stefan
Hi Krzysztof!
I have run also into this problem (trap). Threads in Tcl are different than in Java or C#. The tcl threads are more like new independent processes (at Tcl level).
New Thread in Tcl is just new Interpreter. Interpreter is environment to run Tcl code. (see command interp)
Every interpreter/thread has all internal structures (Tcl methods and verialbes) independent to another interpreter.
You can not share XOTcl Objects between interpreters because object name is just string reference to internal structure of object. Serializing object is probably not the solution for this what you need. You can share only values but not references.
The solution would be create in each thread separate bundle of XOTcl objects that can communicate with each other by sharing values (just strings)
My personal experience is not to use threads at all. You can use internal event handler of Tcl to simulate parallel processing. For example for GUI to program not freezing GUI or aborts buttons.
Use commands: after update vwait (Works also with XOTcl variables)
I have programmed spell checker for editor which runs in "update" loop and for user it seems to be completely parallel. Using tcl threads for it will be overkill. Also programming IO operations (for example Tcl Server) with events is better then using threads. Tcl has good support for asynchronous IO operations.
Tcl has very good event handling loop that is nearly the same that old OS uses (Windows 3.1) to simulate parallel processing. See tcl wiki for some examples.
Artur
Krzysztof Frukacz frukacz.krzysztof@gmail.com hat am 10. Februar 2011 um 14:27 geschrieben:
Hello again,
I am trying to add multi-threaded support for my application. I now face a problem witch combining XOTCl and Thread. The problem is that ::thread::create creates a new instance of interpreter which has own variables. I can have variables shared between threads using ::tsv functions. So here is how it looks:
- Thread #1 creates object myObject and stores in a shared variable:
::tsv::set array1 key1 [MyClass myObject]
- Thread #2 gets the shared variable and tries to call a proc defined
for MyClass: set localVar [::tsv::get array1 key1] $localVar doSomething
At this point second thread will throw en exception saying: Unknown command 'myObject'
What would be the proper way to "register" the object myObject (which already exists) in another thread?
-- Krzysztof _______________________________________________ Xotcl mailing list Xotcl@alice.wu-wien.ac.at http://alice.wu-wien.ac.at/mailman/listinfo/xotcl
Hello everyone,
On 02/11/2011 08:37 AM, mail@xdobry.de wrote:
I have run also into this problem (trap). Threads in Tcl are different than in Java or C#. The tcl threads are more like new independent processes (at Tcl level).
I have noticed that and I must say I really miss that Java/C type threads. I will now describe my problem more generally, maybe somebody will give me a hint on a good solution.
I have a class called Modem. It handles communication with a modem over serial port using AT commands. This class contains for example method sendSMS, that of course sends an SMS message :) I also have other objects that gather data from different sources and they should report it over SMS. I would like to run those in separate threads.
In C/C++/Java I would do that: 1. create Modem object 2. start several threads for data processing objects 3. each data processing object will call [modem sendSMS +49123456789 $reportText ] For C++/Java every thread would get access to single object that handles communication (serial interface cannot be used by two objects at the same time). Of course Modem would implement some synchronization mechanisms like mutex (I find Java's ReentrantLock extremely useful).
I'll be grateful for your suggestions how to do it in XOTcl.
Am 11.02.11 15:09, schrieb Krzysztof Frukacz:
I'll be grateful for your suggestions how to do it in XOTcl.
The following snippet creates a modem thread and a gatherer thread, where the "gatherer" sends from time to time a SMS. The snippet shows some common idioms when working with Tcl-threads. For just solving the task described in the previous mail, the script can be certainly shortened...
gustaf neumann
======================================================================= package require XOTcl package require Thread 2.6 package require xotcl::serializer
tsv::set tid modem [thread::create { package require XOTcl; namespace import ::xotcl::*
# # This is the modem implementation thread; we create here a modem # object that might connect to the real hardware and handles dialing # etc. # ::xotcl::Object create modem modem proc sendSMS {number text} { puts "MODEM dials $number RING RING" puts "MODEM sends text '$text'" }
puts "MODEM waits" thread::wait }]
# # Create a sample gatherer thread # set g1 [thread::create { package require XOTcl; namespace import ::xotcl::*
# # This is a thread that sends from time to time an SMS # ::xotcl::Object create ping ping set count 0 ping proc tick {} { puts stderr "gatherer want to send SMS ..." modem sendSMS +49123456789 counter=[my incr count] after 3000 [list [self] tick] } puts "gatherer waits" thread::wait }]
# # Create a small forwarding stub for interfacing with some # implementation via async messages. # Class create ForwardStub ForwardStub instproc unknown {method args} { set name [namespace tail [self]] thread::send -async [tsv::get tid $name] [list $name $method {*}$args] }
# # Pass the definition of class 'ForwardStub' to the gatherer. The # serialized definition Could be used in a similar way in the init-cmd # of a thread. # thread::send $g1 [::ForwardStub serialize]
# # Create a modem forwarder in the gatherer # thread::send $g1 [list ::ForwardStub create modem]
# # start the work in the gatherer thread # thread::send -async $g1 [list ping tick]
vwait forever =======================================================================