Ticket UUID: | 674367 | |||
Title: | call for a function that is not thread safe | |||
Type: | RFE | Version: | None | |
Submitter: | elfring | Created on: | 2003-01-24 23:39:57 | |
Subsystem: | 80. Thread Package | Assigned To: | vasiljevic | |
Priority: | 5 Medium | Severity: | ||
Status: | Open | Last Modified: | 2003-11-09 23:26:00 | |
Resolution: | None | Closed By: | ||
Closed on: | ||||
Description: |
I describe an use case for the handling of unsafe functions calls with the thread package. I must assume that an application programming interface (like a graphics library or a music API) or even a single function is not thread safe if this property is not described in the documentation for that API. So I must ensure that all unsafe functions are executed by a single thread at each time. I want to create a thread for each function library that must be handled as it has not implemented thread safety at startup/initialization time of my application. I want to achieve that calls into different unsafe libraries can be executed simultaneously. I can perform the call with the function "thread::send" for a thread that has been created before. But I think that I will need a special kind of mutual exclusion. I understand the thread package's documentation in the way that a mutex that is created by the command "thread::mutex create" belongs to the calling thread. It may not be stored in a thread shared variable. Please correct me if I make wrong assumptions here. I guess that the function "thread::eval" does not all what I want and need here. It does not expect a thread indentifier in its argument list. I need a mutex that is global to the process scope (http://citeseer.nj.nec.com/cs?cs=1&q=synchronization+and+global+and+mutex&submit=Documents&co=Expected+Citations&cm=50&cf=Any&ao=Expected+Citations&am=20&af=Any ) to perform a protected and synchronous call of a code piece that should be executed by an other thread. I would like to suggest new functions like the following. 1. thread::mutex::create global or thread::mutex -global create 2. thread::safecall id global_mutex script ?varname? How do you think about this suggestion? Does this use case lead to add more synchronization primitives to the thread package? | |||
User Comments: |
elfring added on 2003-11-09 23:26:00:
Logged In: YES user_id=572001 # Would this implementation have the same effect? namespace eval monitored_executor \ { namespace export do new delete proc do {id work} \ { return [thread::send $id $work] } proc new {} \ { return [thread::create -preserved] } proc delete (id) \ { thread::release $id } } # Did my last point of view from C/C++ make it harder to see the TCL functionality? # Can the requested option "-lock" help if the function "send" is synchronously and completely processed? elfring added on 2003-11-09 02:24:46: File Added - 66887: MonitoredExecutor.zip Logged In: YES user_id=572001 I have added a TCL file. I hope that this source code variant can help to express my ideas and concepts on this topic. elfring added on 2003-11-09 02:21:11: File Deleted - 66706: elfring added on 2003-11-07 04:25:22: File Added - 66706: MonitoredExecutor.zip elfring added on 2003-11-07 04:23:36: File Deleted - 66690: elfring added on 2003-11-07 01:30:28: File Added - 66690: MonitoredExecutor.zip Logged In: YES user_id=572001 I have published the uploaded file also in the forum "class for function calls that are not thread safe" (http://groups.google.de/groups?th=ee30cb7159ff86eb&group=comp.programming.threads). Can it improve TCL source code? elfring added on 2003-09-07 19:57:48: Logged In: YES user_id=572001 1. Are you going to add this description to the documentation? 2. I am looking for a monitor implementation that has got the scope of a library or package and not a single synchronized method or block like it is an Java. A function call will get this monitor as a parameter. vasiljevic added on 2003-07-14 01:36:25: Logged In: YES user_id=95086 Your assumption about mutexes is wrong. Mutex handles can be shared among threads since very nature of the mutex is to synchronize access from many threads. So, handles to mutexes created with tnread::mutex create can be left in thread shared arrays and accesed from many threads simultaneously. The thread package contains examples of Tcl code (web server and command server) where sync techniques with mutexes and condition variables are employed. Zoran elfring added on 2003-07-13 23:08:16: Logged In: YES user_id=572001 Example: It is described on the page "http://tcljava.sourceforge.net/docs/website/getstart.html" how the function "eval" must be protected against multithreaded calls. elfring added on 2003-07-13 20:04:33: Logged In: YES user_id=572001 I hope that my requests "https://sourceforge.net/tracker/?func=detail&aid=770193&group_id=7586&atid=357586" (Boost C++) and "https://sourceforge.net/tracker/?func=detail&aid=712663&group_id=7232&atid=357232" (ZThread) will help for this topic. elfring added on 2003-06-24 22:41:27: Logged In: YES user_id=572001 I assume that the requested function can be implemented with condition variables. But I see an important detail. - The called thread should perform a "thread::cond wait" for the calling thread. The caller will be woken up after the sent script was executed. The scheduling strategy for the calling threads will be an interesting part in the solution. elfring added on 2003-05-11 22:08:56: Logged In: YES user_id=572001 Where and when will our discussion be continued? Here or at the mailing list (more synchronization primitives for the threads package - https://sourceforge.net/mailarchive/forum.php?thread_id=1585197&forum_id=24972)? elfring added on 2003-01-28 03:38:37: Logged In: YES user_id=572001 1. Please add it. I like because it seems to be exatly the enhancement I want. 2. Please add this to the documentation. 3. Yes. Let us continue the discussion on the new mailing list "tcl-threads". vasiljevic added on 2003-01-28 00:49:45: Logged In: YES user_id=95086 1. There is none yet. It was just an idea to see if it would fit. 2. Of course, Just make the catch catch {thread::send $tid $script} or examine return value of: thread::send $tid $script result to be 1 Note that "thread::send $tid $script result" is the same as you would do with: catch {thread::send $tid $script} result BTW, do you mind going to the mail-list for some discussions as Donal suggested? When we come to some nice conclusion we (or you) might post the feature request/bug etc so we do not clutter the SF. It is much more easier to me to answer your questions over email. elfring added on 2003-01-28 00:03:15: Logged In: YES user_id=572001 Well, your last command seems to be very close to my wish. 1. I just do not read an option "-lock" for the function "thread::send" in the HTML documentation at the moment. 2. What will happen if the script that is executed this way by the other thread will "throw" an error? Can the error be caught? vasiljevic added on 2003-01-27 21:15:05: Logged In: YES user_id=95086 Well, returning of values from threads, using the thread::send is already damn-simple. I do not know how to make it simpler. It is either: set result [thread::send $tid "set somevar 12"] or thread::send $tid "set somevar 12" result. What can be simpler than this? If you want to eval the script in an atomic fashion in the other thread, one can perhaps say: thread::send -lock myMutex $tid {open file.txt} result Would this satisfy your requirement? elfring added on 2003-01-27 20:07:44: Logged In: YES user_id=572001 1. Please add your better explanation to the documentation. 2. My intention is just to execute a single function calll under the lock protection. But I think that I will not get the return code of the "unsafe" function "open" in my first version of the example. I will get the return value of the function call "thread::eval" instead. How do you think about it? set $TID [thread::create -preserved] tsv::set X myMutex [thread::mutex create] thread::send $TID \ { thread::eval -lock [tsv::get X myMutex] {catch {open Test.txt w} Test} return $Test } File puts $File Hallo close $File thread::mutex destroy [tsv::get X myMutex] thread::release $TID Can the retrieval for return values from other threads made easier? Does the second example show a use case that can be supported by a single function in the TCL threads API? vasiljevic added on 2003-01-27 15:25:51: Logged In: YES user_id=95086 This example will instruct the $TID thread to open the Test.tst file under lock. If you however want to both open and write to the file in atomic way, you should move the "puts $File" in the thread::eval block. Normally, your application will create some mutexes up front and store them in the shared variable. Those live a long as the app lives and are generally never destroyed. During runtime, threads come and go and they use the precreated mutexes for various sync tasks. elfring added on 2003-01-27 05:16:24: Logged In: YES user_id=572001 2. Or will the following code example do what I want? set $TID [thread::create -preserved] tsv::set X myMutex [thread::mutex create] thread::send $TID \ { thread::eval -lock [tsv::get X myMutex] {open Test.txt} } File puts $File Hallo close $File thread::mutex destroy [tsv::get X myMutex] thread::release $TID elfring added on 2003-01-26 21:07:54: Logged In: YES user_id=572001 1. And your explanation "... this way you can be sure that only *one* thread at a time in the entire process can run ..." is easier to understand than the current description "If no mutex is specified ... an internal static mutex is used". (http://cvs.sourceforge.net/cgi- bin/viewcvs.cgi/*checkout*/tcl/thread/doc/html/thread.html) elfring added on 2003-01-26 20:54:49: Logged In: YES user_id=572001 1. Thanks for your answer. Please add to the documentation that the TCL mutexes have got global scope. (The mutex identifiers should not be stored in local variables. They must be stored in thread shared variables to be useable by all threads.) 2. But I think that something is still missing for the suggested function "thread::safecall id tsvname script ?varname?". I want that a different thread does something with "thread::eval -mutex". How will the calling thread get the return values from the called thread? 3. Will the (missing) sychronization primitives that are described in the chapter "2.3. Interprocess Communication" of the book "Modern Opreation Systems" (http://www.cs.vu.nl/~ast/books/mos2/) be added to the thread package? vasiljevic added on 2003-01-25 16:57:48: Logged In: YES user_id=95086 Mutexes created with "thread::mutex create" are already in the global scope. They can be used from any thread. A mutex tied to a thread has no real benefit. So you're perfectly ok with that. The mutex indentifier returned by "thread::mutex create" can be passed to another thread or stored in the thread shared variable (array) and used from other threads as well. Also, thread::eval is a nice shortcut of thread::mutex lock $mutex # do some Tcl work thread::mutex unlock $mutex so you can just say: thread::eval -mutex $mutex { # do some Tcl work } The benefit is: you can never forget to unlock the mutex. Also, In case of script error, the implementation guarantees that the mutex will be unlocked. Without this you must take care yoursefl about unlocking the mutex which may prove complicated in some cases. A very simplified use of thread eval is: thread.:eval { # do some Tcl wor } where the mutex is implicit and this way you can be sure that only *one* thread at a time in the entire process can run the Tcl code. elfring added on 2003-01-25 16:10:09: Logged In: YES user_id=572001 Values are only available globally with TCL threads if the data is stored in thread shared variables. (http://cvs.sourceforge.net/cgi- bin/viewcvs.cgi/*checkout*/tcl/thread/doc/html/tsv.html). So I adjust my suggestion for the function interface design. The identifier for the mutex object with the global scope must be accessed by a thread shared variable. 1. thread::mutex::create ?tsvname ...? 2. thread::safecall id tsvname script ?varname? |
Attachments:
- MonitoredExecutor.zip [download] added by elfring on 2003-11-09 02:24:46. [details]